1
0
Fork 0
forked from forgejo/forgejo

Compare commits

..

41 commits

Author SHA1 Message Date
Earl Warren
6253ab7bb0 Merge pull request 'Update dependency clippie to v4.1.1' (#3614) from renovate/clippie-4.x into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3614
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-04 15:45:21 +00:00
Earl Warren
385d1d2c24 Merge pull request 'Update dependency vite-string-plugin to v1.3.1' (#3627) from renovate/vite-string-plugin-1.x into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3627
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2024-05-04 15:41:59 +00:00
Earl Warren
96ee3e50a7
chore(renovate): automerge on vite-string-plugin 2024-05-04 08:38:52 +01:00
Earl Warren
c9624d4cdb Merge pull request 'Add an immutable tarball link to archive download headers for Nix' (#3615) from jadeprime/forgejo:jade/nix-tarball-link into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3615
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-04 07:01:02 +00:00
Renovate Bot
526261937d Update dependency vite-string-plugin to v1.3.1 2024-05-04 00:04:51 +00:00
Jade Lovelace
6631f56ebf Add an immutable tarball link to archive download headers for Nix
This allows `nix flake metadata` and nix in general to lock a *branch*
tarball link in a manner that causes it to fetch the correct commit even
if the branch is updated with a newer version.

For further context, Nix flakes are a feature that, among other things,
allows for "inputs" that are "github:someuser/somerepo",
"https://some-tarball-service/some-tarball.tar.gz",
"sourcehut:~meow/nya" or similar. This feature allows our users to fetch
tarballs of git-based inputs to their builds rather than using git to
fetch them, saving significant download time.

There is presently no gitea or forgejo specific fetcher in Nix, and we
don't particularly wish to have one. Ideally (as a developer on a Nix
implementation myself) we could just use the generic tarball fetcher and
not add specific forgejo support, but to do so, we need additional
metadata to know which commit a given *branch* tarball represents, which
is the purpose of the Link header added here.

The result of this patch is that a Nix user can specify `inputs.something.url =
"https://forgejo-host/some/project/archive/main.tar.gz"` in flake.nix
and get a link to some concrete tarball for the actual commit in the
lock file, then when they run `nix flake update` in the future, they
will get the latest commit in that branch.

Example of it working locally:

 » nix flake metadata --refresh 'http://localhost:3000/api/v1/repos/jade/cats/archive/main.tar.gz?dir=configs/nix'
Resolved URL:  http://localhost:3000/api/v1/repos/jade/cats/archive/main.tar.gz?dir=configs/nix
Locked URL:    804ede182b.tar.gz?dir=configs
/nix&narHash=sha256-yP7KkDVfuixZzs0fsqhSETXFC0y8m6nmPLw2GrAMxKQ%3D
Description:   Computers with the nixos
Path:          /nix/store/s856c6yqghyan4v0zy6jj19ksv0q22nx-source
Revision:      804ede182b6b66469b23ea4d21eece52766b7a06
Last modified: 2024-05-02 00:48:32

For details on the header value, see:
56763ff918/doc/manual/src/protocols/tarball-fetcher.md
2024-05-03 15:21:45 -07:00
Earl Warren
f866bf8dbe Merge pull request 'chore(renovate): fix config' (#3622) from viceice/forgejo:chore/renovate-reconfigure into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3622
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Reviewed-by: Otto <otto@codeberg.org>
2024-05-03 17:16:08 +00:00
Michael Kriese
28d186a13d
chore(renovate): fix config 2024-05-03 14:00:29 +02:00
Earl Warren
fbbbd36535 Merge pull request 'chore(renovate): reconfigure node versioning' (#3617) from viceice/forgejo:chore/renovate-reconfigure into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3617
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-03 09:46:15 +00:00
Earl Warren
ff328f0f6f Merge pull request 'Update dependency markdownlint-cli to v0.40.0' (#3600) from renovate/markdownlint-cli-0.x into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3600
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2024-05-03 09:39:24 +00:00
Earl Warren
d0708b0051 Merge pull request 'Update dependency @stylistic/eslint-plugin-js to v1.8.0' (#3599) from renovate/stylistic-eslint-plugin-js-1.x into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3599
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2024-05-03 09:38:46 +00:00
Michael Kriese
baa7c8f975
chore(renovate): reconfigure node versioning 2024-05-03 09:08:03 +02:00
Renovate Bot
ab23f5e6cd Update dependency clippie to v4.1.1 2024-05-03 06:03:34 +00:00
Earl Warren
85f2727872 Merge pull request 'Fix text selection color' (#3608) from 0ko/forgejo:fix-color-sel into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3608
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-02 17:44:36 +00:00
0ko
787b16a7be [THEME] fix text selection color
regression of c2280a2009
2024-05-02 21:31:03 +05:00
JakobDev
d50efa626a Show repo count in blocked users tab (#3601)
Fixes #3595

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3601
Reviewed-by: Otto <otto@codeberg.org>
Co-authored-by: JakobDev <jakobdev@gmx.de>
Co-committed-by: JakobDev <jakobdev@gmx.de>
2024-05-02 15:51:27 +00:00
Earl Warren
9bc866124b Merge pull request 'Use PostFormValue instead of PostForm.Get' (#3563) from algernon/forgejo:s/Req.PostForm.Get/Req.PostFormValue/g into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3563
Reviewed-by: Otto <otto@codeberg.org>
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-02 15:48:28 +00:00
Gergely Nagy
b08aef967e
Use PostFormValue instead of PostForm.Get
In `repo.RemoveDependency`, use `PostFormValue` instead of
`PostForm.Get`. The latter requires `ParseForm()` to be called prior,
and in this case, has no benefit over `PostFormValue` anyway (which
calls `ParseForm()` if necessary).

While this currently does not cause any issue as far as I can tell, it
feels like a bug lying in wait for the perfect opportunity. Lets squash
it before it can do harm.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
2024-05-02 10:51:07 +02:00
Renovate Bot
47ea0f5f98 Update dependency markdownlint-cli to v0.40.0 2024-05-02 02:04:58 +00:00
Renovate Bot
3e3f7c3f47 Update dependency @stylistic/eslint-plugin-js to v1.8.0 2024-05-02 02:04:31 +00:00
Earl Warren
cd6ae89cd9 Merge pull request 'markup: Allow cross references to contain URL query parameters too' (#3584) from algernon/forgejo:a-capture-group-a-day-keeps-the-query-params-away into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3584
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-02 01:15:35 +00:00
Gergely Nagy
8164ef9762
markup: Allow cross references to contain URL query parameters too
Adjust the `anyHashPattern` to match URL query parameters too, and
adjust `fullHashPatternProcessor` accordingly.

Includes a test case, and an update to an existing one to account for
the new capture group.

Fixes #3548.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
2024-05-01 21:14:16 +02:00
0ko
d096a21da6 Fix inconsistent required field (#3583)
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3583
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Reviewed-by: Otto <otto@codeberg.org>
2024-05-01 18:29:42 +00:00
varp0n
4a2959b3ec FIX gogs migration if gogs is hosted at a subpath (#3572)
Also add a test for GogsDownloaderFactory.New() to make sure
that the URL of the source repository is parsed correctly.

When the source gogs instance is hosted at a subpath like `https://git.example.com/gogs/<username>/<reponame>` the migration fails.
This PR fixes that.

Co-authored-by: hecker <tomas.hecker@gmail.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3572
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Co-authored-by: varp0n <tom@gkstn.de>
Co-committed-by: varp0n <tom@gkstn.de>
2024-05-01 16:28:44 +00:00
Earl Warren
c6cc1430a9 Merge pull request 'docs(release-notes): 7.0.2' (#3561) from earl-warren/forgejo:wip-release-notes-v7.0 into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3561
Reviewed-by: twenty-panda <twenty-panda@noreply.codeberg.org>
2024-05-01 12:59:00 +00:00
Earl Warren
a050b546b9
[skip ci] docs(release-notes): 7.0.2 2024-05-01 14:22:18 +02:00
Earl Warren
39732d74c9 Merge pull request 'Fix Issue watching / unwatching on the web ui' (#3562) from algernon/forgejo:vogon-poetry into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3562
Reviewed-by: Otto <otto@codeberg.org>
Reviewed-by: crystal <crystal@noreply.codeberg.org>
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-01 10:35:48 +00:00
Gergely Nagy
21911bfe57
Add a test case for unsubscribing from an issue
Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
2024-05-01 11:06:38 +02:00
Gergely Nagy
8cc5d5dc78
tests: Support creating a declarative repo without AutoInit
To be able to easily test cases where the repository does not have any
code, where the git repo itself is completely uninitialized, lets
support a case where the `AutoInit` property is false.

For the sake of backwards compatibility, if the option is not set either
way, it will default to `true`.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
2024-05-01 11:06:38 +02:00
Gergely Nagy
632a274b8f
Fix Issue watching / unwatching on the web ui
When subscribing or unsubscribing to/from an issue on the web ui, the
request was posted to a route handled by `repo.IssueWatch`. This
function used `ctx.Req.PostForm.Get()`, erroneously.

`request.PostForm` is *only* available if `request.ParseForm()` has been
called before it. The function in question did not do that. Under some
circumstances, something, somewhere did end up calling `ParseForm()`,
but not in every scenario.

Since we do not need to check for multiple values, the easiest fix here
is to use `ctx.Req.PostFormValue`, which will call `ParseForm()` if
necessary.

Fixes #3516.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
2024-05-01 11:04:54 +02:00
Earl Warren
97ef18db65 Merge pull request 'Update dependency vue to v3.4.26' (#3439) from renovate/vue-monorepo into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3439
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-01 08:08:52 +00:00
Earl Warren
0978095a37 Merge pull request 'Update ghcr.io/visualon/renovate Docker tag to v37.330.1' (#3490) from renovate/ghcr.io-visualon-renovate-37.x into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3490
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-01 07:26:21 +00:00
Earl Warren
cf16782338 Merge pull request 'Update dependency dayjs to v1.11.11' (#3545) from renovate/dayjs-1.x into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3545
Reviewed-by: Michael Kriese <michael.kriese@gmx.de>
2024-05-01 07:25:09 +00:00
Earl Warren
8f93ac7e7a Merge pull request 'feat: UI: use full screen height for displaying pdf files' (#3434) from Beowulf/forgejo:full-screen-height-pdf into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3434
Reviewed-by: Otto <otto@codeberg.org>
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-01 07:03:15 +00:00
Earl Warren
756bb7f6e1 Merge pull request 'UI: Actions: Replace runs list description semicolon' (#3534) from n0toose/settings/runs-list-colon-brist into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3534
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
2024-05-01 06:59:53 +00:00
Earl Warren
ee52a8e805 Merge pull request '[I18N] Fix tepository->repository typo' (#3539) from proton-ab/forgejo:patch-1 into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3539
Reviewed-by: Otto <otto@codeberg.org>
2024-05-01 06:58:48 +00:00
Renovate Bot
15978d4d07 Update ghcr.io/visualon/renovate Docker tag to v37.330.1 2024-05-01 06:02:32 +00:00
Renovate Bot
a7fcc3ca3f Update dependency dayjs to v1.11.11 2024-04-30 00:11:43 +00:00
proton-ab
5ed3ffc0c8 [I18N] Fix tepository->repository typo
Signed-off-by: proton-ab <proton_ab@tuta.io>
2024-04-29 22:17:18 +00:00
Panagiotis "Ivory" Vasilopoulos
870a1c85c7 UI: Actions: Replace runs list description semicolon
The current format makes the text look somewhat like this:

```
testing.yml #15065 :Commit 103306f00c pushed by n0toose
```

This looks wrong. We will have to work on that list at a later point
in time anyways, as well as make the way that we separate information
in subheaders in lists like this one more consistent.

However, this should do for now.

This change should make each entry look like this instead:

```
testing.yml #15065 - Commit 103306f00c pushed by n0toose
```
2024-04-29 21:05:20 +02:00
Beowulf
9035b400a6
UI: use full screen height for displaying pdf files 2024-04-26 20:42:45 +02:00
33 changed files with 540 additions and 83 deletions

View file

@ -22,7 +22,7 @@ jobs:
runs-on: docker
container:
image: ghcr.io/visualon/renovate:37.323.3
image: ghcr.io/visualon/renovate:37.330.1
steps:
- name: Load renovate repo cache

View file

@ -8,6 +8,23 @@ A [patch or minor release](https://semver.org/spec/v2.0.0.html) (e.g. upgrading
- [8.0.0](/release-notes/8.0.0/)
## 7.0.2
This is a bug fix release. See the documentation for more information on the [upgrade procedure](https://forgejo.org/docs/v7.0/admin/upgrade/).
In addition to the following notable bug fixes, you can browse the [full list of commits](https://codeberg.org/forgejo/forgejo/compare/v7.0.1...v7.0.2) included in this release.
* **Bug fixes:**
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3562): a v7.0.0 regression where subscribing to or unsubscribing from an issue in a repository with no code produced an internal server error.
* [PR](https://codeberg.org/forgejo/forgejo/issues/3559): a v7.0.0 regression makes all the refs sent in Gitea webhooks to be full refs and might break Woodpecker CI pipelines triggered on tag (`CI_COMMIT_TAG` contained the full ref). This issue [has been fixed](https://github.com/woodpecker-ci/woodpecker/pull/3664) in the `main` branch of Woodpecker CI as well.
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3555): the webhook branch filter wrongly applied the match on the full ref for branch creation and deletion (wrongly skipping events).
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3537): toggling the WIP state of a pull request is possible from the sidebar, but not from the footer.
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3565): when mentioning a user, the markup post-processor does not handle the case where the mentioned user does not exist: it tries to skip to the next node, which in turn, ended up skipping the rest of the line.
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3570): excessive and unnecessary database queries when a user with no repositories is viewing their dashboard.
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3580): duplicate status check contexts show in the branch protection settings.
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3497): profile info fails to render german singular translation.
* [PR](https://codeberg.org/forgejo/forgejo/pulls/3504): inline attachments of [incoming emails](https://forgejo.org/docs/v7.0/user/incoming/) (as they occur for example with Apple Mail) are not attached to comments.
## 7.0.1
This is a bug fix release. See the documentation for more information on the [upgrade procedure](https://forgejo.org/docs/v7.0/admin/upgrade/).
@ -34,6 +51,7 @@ $ git -C forgejo log --oneline --no-merges origin/v1.21/forgejo..origin/v7.0/for
* 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:**
* [Forgejo webhooks](https://codeberg.org/forgejo/forgejo/issues/3055) now always send full refs (starting with `refs/`) instead of sending short refs in some cases. This new behavior may require changes when the receiving end assumes a short ref will be received (for instance some versions of Woodpecker CI when receiving webhook payloads when a tag is set).
* [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.
* The date format of the `created` and `last_update` fields of the [`/repos/{owner}/{repo}/push_mirrors`](https://code.forgejo.org/api/swagger/#/repository/repoListPushMirrors) and [/repos/{owner}/{repo}/push_mirrors](https://code.forgejo.org/api/swagger/#/repository/repoAddPushMirror) API endpoint changed [to be timestamps instead of numbers](https://codeberg.org/forgejo/forgejo/commit/0ee7cbf725f45650136be45f8e0f74d395f73b5c).

View file

@ -54,7 +54,7 @@ var (
shortLinkPattern = regexp.MustCompile(`\[\[(.*?)\]\](\w*)`)
// anySHA1Pattern splits url containing SHA into parts
anyHashPattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40,64})(/[-+~_%.a-zA-Z0-9/]+)?(#[-+~_%.a-zA-Z0-9]+)?`)
anyHashPattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{40,64})(/[-+~_%.a-zA-Z0-9/]+)?(\?[-+~_%\.a-zA-Z0-9=&]+)?(#[-+~_%.a-zA-Z0-9]+)?`)
// comparePattern matches "http://domain/org/repo/compare/COMMIT1...COMMIT2#hash"
comparePattern = regexp.MustCompile(`https?://(?:\S+/){4,5}([0-9a-f]{7,64})(\.\.\.?)([0-9a-f]{7,64})?(#[-+~_%.a-zA-Z0-9]+)?`)
@ -969,10 +969,10 @@ func fullHashPatternProcessor(ctx *RenderContext, node *html.Node) {
subpath = node.Data[m[4]:m[5]]
}
// 4th capture group matches a optional url hash
// 5th capture group matches a optional url hash
hash := ""
if m[7] > 0 {
hash = node.Data[m[6]:m[7]][1:]
if m[9] > 0 {
hash = node.Data[m[8]:m[9]][1:]
}
start := m[0]

View file

@ -403,28 +403,39 @@ func TestRegExp_anySHA1Pattern(t *testing.T) {
"https://github.com/jquery/jquery/blob/a644101ed04d0beacea864ce805e0c4f86ba1cd1/test/unit/event.js#L2703": {
"a644101ed04d0beacea864ce805e0c4f86ba1cd1",
"/test/unit/event.js",
"",
"#L2703",
},
"https://github.com/jquery/jquery/blob/a644101ed04d0beacea864ce805e0c4f86ba1cd1/test/unit/event.js": {
"a644101ed04d0beacea864ce805e0c4f86ba1cd1",
"/test/unit/event.js",
"",
"",
},
"https://github.com/jquery/jquery/commit/0705be475092aede1eddae01319ec931fb9c65fc": {
"0705be475092aede1eddae01319ec931fb9c65fc",
"",
"",
"",
},
"https://github.com/jquery/jquery/tree/0705be475092aede1eddae01319ec931fb9c65fc/src": {
"0705be475092aede1eddae01319ec931fb9c65fc",
"/src",
"",
"",
},
"https://try.gogs.io/gogs/gogs/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2": {
"d8a994ef243349f321568f9e36d5c3f444b99cae",
"",
"",
"#diff-2",
},
"https://codeberg.org/forgejo/forgejo/src/commit/949ab9a5c4cac742f84ae5a9fa186f8d6eb2cdc0/RELEASE-NOTES.md?display=source&w=1#L7-L9": {
"949ab9a5c4cac742f84ae5a9fa186f8d6eb2cdc0",
"/RELEASE-NOTES.md",
"?display=source&w=1",
"#L7-L9",
},
}
for k, v := range testCases {

View file

@ -127,6 +127,12 @@ func TestRender_CrossReferences(t *testing.T) {
test(
util.URLJoin(markup.TestAppURL, "gogitea", "some-repo-name", "issues", "12345"),
`<p><a href="`+util.URLJoin(markup.TestAppURL, "gogitea", "some-repo-name", "issues", "12345")+`" class="ref-issue" rel="nofollow">gogitea/some-repo-name#12345</a></p>`)
sha := "65f1bf27bc3bf70f64657658635e66094edbcb4d"
urlWithQuery := util.URLJoin(markup.TestAppURL, "forgejo", "some-repo-name", "commit", sha, "README.md") + "?display=source#L1-L5"
test(
urlWithQuery,
`<p><a href="`+urlWithQuery+`" rel="nofollow"><code>`+sha[:10]+`/README.md (L1-L5)</code></a></p>`)
}
func TestMisc_IsSameDomain(t *testing.T) {

View file

@ -2748,7 +2748,7 @@ team_name_helper = Team names should be short and memorable.
team_desc_helper = Describe the purpose or role of the team.
team_access_desc = Repository access
team_permission_desc = Permission
team_unit_desc = Allow access to tepository sections
team_unit_desc = Allow access to repository sections
team_unit_disabled = (Disabled)
follow_blocked_user = You cannot follow this organisation because this organisation has blocked you.

102
package-lock.json generated
View file

@ -20,9 +20,9 @@
"chart.js": "4.4.2",
"chartjs-adapter-dayjs-4": "1.0.4",
"chartjs-plugin-zoom": "2.0.1",
"clippie": "4.0.7",
"clippie": "4.1.1",
"css-loader": "7.0.0",
"dayjs": "1.11.10",
"dayjs": "1.11.11",
"dropzone": "6.0.0-beta.2",
"easymde": "2.18.0",
"esbuild-loader": "4.1.0",
@ -67,7 +67,7 @@
"@eslint-community/eslint-plugin-eslint-comments": "4.3.0",
"@playwright/test": "1.43.0",
"@stoplight/spectral-cli": "6.11.1",
"@stylistic/eslint-plugin-js": "1.7.2",
"@stylistic/eslint-plugin-js": "1.8.0",
"@stylistic/stylelint-plugin": "2.1.2",
"@vitejs/plugin-vue": "5.0.4",
"@vue/test-utils": "2.4.5",
@ -87,7 +87,7 @@
"eslint-plugin-vue-scoped-css": "2.8.0",
"eslint-plugin-wc": "2.1.0",
"happy-dom": "14.7.1",
"markdownlint-cli": "0.39.0",
"markdownlint-cli": "0.40.0",
"postcss-html": "1.6.0",
"stylelint": "16.4.0",
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
@ -95,7 +95,7 @@
"stylelint-value-no-unknown-custom-properties": "6.0.1",
"svgo": "3.2.0",
"updates": "16.0.1",
"vite-string-plugin": "1.2.0",
"vite-string-plugin": "1.3.1",
"vitest": "1.5.3"
},
"engines": {
@ -2126,12 +2126,12 @@
}
},
"node_modules/@stylistic/eslint-plugin-js": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.7.2.tgz",
"integrity": "sha512-ZYX7C5p7zlHbACwFLU+lISVh6tdcRP/++PWegh2Sy0UgMT5kU0XkPa2tKWEtJYzZmPhJxu9LxbnWcnE/tTwSDQ==",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-1.8.0.tgz",
"integrity": "sha512-jdvnzt+pZPg8TfclZlTZPiUbbima93ylvQ+wNgHLNmup3obY6heQvgewSu9i2CfS61BnRByv+F9fxQLPoNeHag==",
"dev": true,
"dependencies": {
"@types/eslint": "^8.56.8",
"@types/eslint": "^8.56.10",
"acorn": "^8.11.3",
"escape-string-regexp": "^4.0.0",
"eslint-visitor-keys": "^3.4.3",
@ -2224,9 +2224,9 @@
}
},
"node_modules/@types/eslint": {
"version": "8.56.9",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.9.tgz",
"integrity": "sha512-W4W3KcqzjJ0sHg2vAq9vfml6OhsJ53TcUjUqfzzZf/EChUtwspszj/S0pzMxnfRcO55/iGq47dscXw71Fxc4Zg==",
"version": "8.56.10",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz",
"integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==",
"dependencies": {
"@types/estree": "*",
"@types/json-schema": "*"
@ -3779,9 +3779,9 @@
}
},
"node_modules/clippie": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/clippie/-/clippie-4.0.7.tgz",
"integrity": "sha512-xmIARCRFQUoCR0kNNu4uIv5f/IFqM1fUts0vQwt1hQEdCPEqs3/dTaG38WenlWOgs3Fcn73PBYXbPIVSlOgFRw=="
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/clippie/-/clippie-4.1.1.tgz",
"integrity": "sha512-D9OOW77Kkj9YEiDXTQjZJZLvTjJPEmK2IBx8JbGJIZaqVd8RvSvxwIN4KVSEFQfu9Jh0z5FL6Pdc4SIknllFFA=="
},
"node_modules/cliui": {
"version": "7.0.4",
@ -4631,9 +4631,9 @@
}
},
"node_modules/dayjs": {
"version": "1.11.10",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
"integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ=="
"version": "1.11.11",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz",
"integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
},
"node_modules/debug": {
"version": "4.3.4",
@ -8212,9 +8212,9 @@
}
},
"node_modules/markdown-it": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.0.0.tgz",
"integrity": "sha512-seFjF0FIcPt4P9U39Bq1JYblX0KZCjDLFFQPHpL5AzHpqPEKtosxmdq/LTVZnjfH7tjt9BxStm+wXcDBNuYmzw==",
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1",
@ -8222,20 +8222,20 @@
"linkify-it": "^5.0.0",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.0.0"
"uc.micro": "^2.1.0"
},
"bin": {
"markdown-it": "bin/markdown-it.mjs"
}
},
"node_modules/markdownlint": {
"version": "0.33.0",
"resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.33.0.tgz",
"integrity": "sha512-4lbtT14A3m0LPX1WS/3d1m7Blg+ZwiLq36WvjQqFGsX3Gik99NV+VXp/PW3n+Q62xyPdbvGOCfjPqjW+/SKMig==",
"version": "0.34.0",
"resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.34.0.tgz",
"integrity": "sha512-qwGyuyKwjkEMOJ10XN6OTKNOVYvOIi35RNvDLNxTof5s8UmyGHlCdpngRHoRGNvQVGuxO3BJ7uNSgdeX166WXw==",
"dev": true,
"dependencies": {
"markdown-it": "14.0.0",
"markdownlint-micromark": "0.1.8"
"markdown-it": "14.1.0",
"markdownlint-micromark": "0.1.9"
},
"engines": {
"node": ">=18"
@ -8245,20 +8245,22 @@
}
},
"node_modules/markdownlint-cli": {
"version": "0.39.0",
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.39.0.tgz",
"integrity": "sha512-ZuFN7Xpsbn1Nbp0YYkeLOfXOMOfLQBik2lKRy8pVI/llmKQ2uW7x+8k5OMgF6o7XCsTDSYC/OOmeJ+3qplvnJQ==",
"version": "0.40.0",
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.40.0.tgz",
"integrity": "sha512-JXhI3dRQcaqwiFYpPz6VJ7aKYheD53GmTz9y4D/d0F1MbZDGOp9pqKlbOfUX/pHP/iAoeiE4wYRmk8/kjLakxA==",
"dev": true,
"dependencies": {
"commander": "~11.1.0",
"commander": "~12.0.0",
"get-stdin": "~9.0.0",
"glob": "~10.3.10",
"ignore": "~5.3.0",
"glob": "~10.3.12",
"ignore": "~5.3.1",
"js-yaml": "^4.1.0",
"jsonc-parser": "~3.2.1",
"markdownlint": "~0.33.0",
"minimatch": "~9.0.3",
"run-con": "~1.3.2"
"jsonpointer": "5.0.1",
"markdownlint": "~0.34.0",
"minimatch": "~9.0.4",
"run-con": "~1.3.2",
"toml": "~3.0.0"
},
"bin": {
"markdownlint": "markdownlint.js"
@ -8268,12 +8270,12 @@
}
},
"node_modules/markdownlint-cli/node_modules/commander": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-12.0.0.tgz",
"integrity": "sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA==",
"dev": true,
"engines": {
"node": ">=16"
"node": ">=18"
}
},
"node_modules/markdownlint-cli/node_modules/glob": {
@ -8305,12 +8307,12 @@
"dev": true
},
"node_modules/markdownlint-micromark": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.8.tgz",
"integrity": "sha512-1ouYkMRo9/6gou9gObuMDnvZM8jC/ly3QCFQyoSPCS2XV1ZClU0xpKbL1Ar3bWWRT1RnBZkWUEiNKrI2CwiBQA==",
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.9.tgz",
"integrity": "sha512-5hVs/DzAFa8XqYosbEAEg6ok6MF2smDj89ztn9pKkCtdKHVdPQuGMH7frFfYL9mLkvfFe4pTyAMffLbjf3/EyA==",
"dev": true,
"engines": {
"node": ">=16"
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/DavidAnson"
@ -11831,6 +11833,12 @@
"resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz",
"integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ=="
},
"node_modules/toml": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
"dev": true
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@ -12279,9 +12287,9 @@
}
},
"node_modules/vite-string-plugin": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/vite-string-plugin/-/vite-string-plugin-1.2.0.tgz",
"integrity": "sha512-IijlLgTxUDUwOpLoBLZCZO2us4fZWPRpj8XWoD9OAYjjUEge8enV4gaDTOs7uEsC8EJ9+NmusdLwmgWajFO45Q==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/vite-string-plugin/-/vite-string-plugin-1.3.1.tgz",
"integrity": "sha512-0Wu9yNw4QlSVM4SlwozzxR0geMoKFrAIpMldgPuzDvV8lWT1v+0pFXYt+t48qocYXBaxiuVRE3qcsEwFDHBAmA==",
"dev": true
},
"node_modules/vite/node_modules/@types/estree": {

View file

@ -19,9 +19,9 @@
"chart.js": "4.4.2",
"chartjs-adapter-dayjs-4": "1.0.4",
"chartjs-plugin-zoom": "2.0.1",
"clippie": "4.0.7",
"clippie": "4.1.1",
"css-loader": "7.0.0",
"dayjs": "1.11.10",
"dayjs": "1.11.11",
"dropzone": "6.0.0-beta.2",
"easymde": "2.18.0",
"esbuild-loader": "4.1.0",
@ -66,7 +66,7 @@
"@eslint-community/eslint-plugin-eslint-comments": "4.3.0",
"@playwright/test": "1.43.0",
"@stoplight/spectral-cli": "6.11.1",
"@stylistic/eslint-plugin-js": "1.7.2",
"@stylistic/eslint-plugin-js": "1.8.0",
"@stylistic/stylelint-plugin": "2.1.2",
"@vitejs/plugin-vue": "5.0.4",
"@vue/test-utils": "2.4.5",
@ -86,7 +86,7 @@
"eslint-plugin-vue-scoped-css": "2.8.0",
"eslint-plugin-wc": "2.1.0",
"happy-dom": "14.7.1",
"markdownlint-cli": "0.39.0",
"markdownlint-cli": "0.40.0",
"postcss-html": "1.6.0",
"stylelint": "16.4.0",
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
@ -94,7 +94,7 @@
"stylelint-value-no-unknown-custom-properties": "6.0.1",
"svgo": "3.2.0",
"updates": "16.0.1",
"vite-string-plugin": "1.2.0",
"vite-string-plugin": "1.3.1",
"vitest": "1.5.3"
},
"browserslist": ["defaults"]

View file

@ -0,0 +1 @@
Fix gogs migration if gogs is hosted at a subpath

View file

@ -0,0 +1 @@
Settings: OAuth2 applications: Consistently check input on client side

View file

@ -0,0 +1 @@
Fix text selection color

View file

@ -0,0 +1 @@
When PDFs are displayed in the repository, the [full height of the screen](https://codeberg.org/forgejo/forgejo/pulls/3434) is now used instead of a predefined fixed height

View file

@ -0,0 +1,5 @@
Support the [Nix tarball fetcher immutable link protocol](https://github.com/nixos/nix/blob/56763ff918eb308db23080e560ed2ea3e00c80a7/doc/manual/src/protocols/tarball-fetcher.md) on archive URLs, so Forgejo-generated tarballs for branches will go into Nix's `flake.lock` as their respective commit URLs and `nix flake update` will just work. This allows natively fetching Forgejo repositories for Nix flake inputs as tarballs rather than as Git repositories, significantly improving fetch times and avoiding depending on Git at runtime.
Concretely, Forgejo now returns a header of the following format from its archive URLs: `Link: <https://my-forgejo/api/v1/someuser/somerepo/archive/some-commit-hash.tar.gz?rev=some-commit-hash> rel="immutable"`.
Example usage: `inputs.meow.url = "https://my-forgejo/someuser/somerepo/archive/main.tar.gz";` in `flake.nix`. For a private repository, configure `netrc-file` in `nix.conf` and use `https://my-forgejo/api/v1/repos/someuser/somerepo/archive/main.tar.gz` as a URL instead, since the normal archive endpoint doesn't support tokens.

View file

@ -1 +0,0 @@
Fixed that inline attachments of emails (as they occur for example with Apple Mail) are not attached to comments.

View file

@ -1 +0,0 @@
Fixed an issue that resulted in excessive and unnecessary database queries when a user with no repositories was viewing their dashboard.

View file

@ -60,7 +60,9 @@
{
"description": "Group nodejs packages",
"matchDepNames": ["node", "docker.io/node", "docker.io/library/node"],
"groupName": "nodejs packages"
"groupName": "nodejs packages",
"versionCompatibility": "^(?<version>[^-]+)(?<compatibility>-.*)?$",
"versioning": "node"
},
{
"description": "Automerge renovate updates",
@ -71,20 +73,12 @@
},
{
"description": "Split minor and patch updates",
"matchDepNames": [
"vue",
"github.com/urfave/cli/v2",
"swagger-ui-dist"
],
"matchDepNames": ["vue", "github.com/urfave/cli/v2", "swagger-ui-dist"],
"separateMinorPatch": true
},
{
"description": "Automerge patch updates",
"matchDepNames": [
"vue",
"github.com/urfave/cli/v2",
"swagger-ui-dist"
],
"matchDepNames": ["vue", "github.com/urfave/cli/v2", "swagger-ui-dist"],
"matchUpdateTypes": ["patch"],
"automerge": true
},
@ -103,7 +97,7 @@
{
"description": "Automerge some packages when ci succeeds",
"extends": ["packages:linters"],
"matchDepNames": ["vitest"],
"matchDepNames": ["vitest", "vite-string-plugin"],
"automerge": true
},
{

View file

@ -326,6 +326,12 @@ func archiveDownload(ctx *context.APIContext) {
func download(ctx *context.APIContext, archiveName string, archiver *repo_model.RepoArchiver) {
downloadName := ctx.Repo.Repository.Name + "-" + archiveName
// Add nix format link header so tarballs lock correctly:
// https://github.com/nixos/nix/blob/56763ff918eb308db23080e560ed2ea3e00c80a7/doc/manual/src/protocols/tarball-fetcher.md
ctx.Resp.Header().Add("Link", fmt.Sprintf("<%s/archive/%s.tar.gz?rev=%s>; rel=\"immutable\"",
ctx.Repo.Repository.APIURL(),
archiver.CommitID, archiver.CommitID))
rPath := archiver.RelativePath()
if setting.RepoArchive.Storage.MinioConfig.ServeDirect {
// If we have a signed url (S3, object storage), redirect to this directly.

View file

@ -10,6 +10,7 @@ import (
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
user_service "code.gitea.io/gitea/services/user"
)
@ -27,6 +28,12 @@ func BlockedUsers(ctx *context.Context) {
return
}
err = shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return
}
ctx.Data["BlockedUsers"] = blockedUsers
ctx.HTML(http.StatusOK, tplBlockedUsers)

View file

@ -109,7 +109,7 @@ func RemoveDependency(ctx *context.Context) {
}
// Dependency Type
depTypeStr := ctx.Req.PostForm.Get("dependencyType")
depTypeStr := ctx.Req.PostFormValue("dependencyType")
var depType issues_model.DependencyType

View file

@ -46,7 +46,7 @@ func IssueWatch(ctx *context.Context) {
return
}
watch, err := strconv.ParseBool(ctx.Req.PostForm.Get("watch"))
watch, err := strconv.ParseBool(ctx.Req.PostFormValue("watch"))
if err != nil {
ctx.ServerError("watch is not bool", err)
return

View file

@ -480,6 +480,12 @@ func Download(ctx *context.Context) {
func download(ctx *context.Context, archiveName string, archiver *repo_model.RepoArchiver) {
downloadName := ctx.Repo.Repository.Name + "-" + archiveName
// Add nix format link header so tarballs lock correctly:
// https://github.com/nixos/nix/blob/56763ff918eb308db23080e560ed2ea3e00c80a7/doc/manual/src/protocols/tarball-fetcher.md
ctx.Resp.Header().Add("Link", fmt.Sprintf("<%s/archive/%s.tar.gz?rev=%s>; rel=\"immutable\"",
ctx.Repo.Repository.APIURL(),
archiver.CommitID, archiver.CommitID))
rPath := archiver.RelativePath()
if setting.RepoArchive.Storage.MinioConfig.ServeDirect {
// If we have a signed url (S3, object storage), redirect to this directly.

View file

@ -38,17 +38,24 @@ func (f *GogsDownloaderFactory) New(ctx context.Context, opts base.MigrateOption
return nil, err
}
baseURL := u.Scheme + "://" + u.Host
repoNameSpace := strings.TrimSuffix(u.Path, ".git")
repoNameSpace = strings.Trim(repoNameSpace, "/")
fields := strings.Split(repoNameSpace, "/")
if len(fields) < 2 {
numFields := len(fields)
if numFields < 2 {
return nil, fmt.Errorf("invalid path: %s", repoNameSpace)
}
log.Trace("Create gogs downloader. BaseURL: %s RepoOwner: %s RepoName: %s", baseURL, fields[0], fields[1])
return NewGogsDownloader(ctx, baseURL, opts.AuthUsername, opts.AuthPassword, opts.AuthToken, fields[0], fields[1]), nil
repoOwner := fields[numFields-2]
repoName := fields[numFields-1]
u.Path = ""
u = u.JoinPath(fields[:numFields-2]...)
baseURL := u.String()
log.Trace("Create gogs downloader. BaseURL: %s RepoOwner: %s RepoName: %s", baseURL, repoOwner, repoName)
return NewGogsDownloader(ctx, baseURL, opts.AuthUsername, opts.AuthPassword, opts.AuthToken, repoOwner, repoName), nil
}
// GitServiceType returns the type of git service

View file

@ -137,3 +137,87 @@ func TestGogsDownloadRepo(t *testing.T) {
_, _, err = downloader.GetPullRequests(1, 3)
assert.Error(t, err)
}
func TestGogsDownloaderFactory_New(t *testing.T) {
tests := []struct {
name string
args base.MigrateOptions
baseURL string
repoOwner string
repoName string
wantErr bool
}{
{
name: "Gogs_at_root",
args: base.MigrateOptions{
CloneAddr: "https://git.example.com/user/repo.git",
AuthUsername: "username",
AuthPassword: "password",
AuthToken: "authtoken",
},
baseURL: "https://git.example.com/",
repoOwner: "user",
repoName: "repo",
wantErr: false,
},
{
name: "Gogs_at_sub_path",
args: base.MigrateOptions{
CloneAddr: "https://git.example.com/subpath/user/repo.git",
AuthUsername: "username",
AuthPassword: "password",
AuthToken: "authtoken",
},
baseURL: "https://git.example.com/subpath",
repoOwner: "user",
repoName: "repo",
wantErr: false,
},
{
name: "Gogs_at_2nd_sub_path",
args: base.MigrateOptions{
CloneAddr: "https://git.example.com/sub1/sub2/user/repo.git",
AuthUsername: "username",
AuthPassword: "password",
AuthToken: "authtoken",
},
baseURL: "https://git.example.com/sub1/sub2",
repoOwner: "user",
repoName: "repo",
wantErr: false,
},
{
name: "Gogs_URL_too_short",
args: base.MigrateOptions{
CloneAddr: "https://git.example.com/repo.git",
AuthUsername: "username",
AuthPassword: "password",
AuthToken: "authtoken",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f := &GogsDownloaderFactory{}
opts := base.MigrateOptions{
CloneAddr: tt.args.CloneAddr,
AuthUsername: tt.args.AuthUsername,
AuthPassword: tt.args.AuthPassword,
AuthToken: tt.args.AuthToken,
}
got, err := f.New(context.Background(), opts)
if (err != nil) != tt.wantErr {
t.Errorf("GogsDownloaderFactory.New() error = %v, wantErr %v", err, tt.wantErr)
return
} else if err != nil {
return
}
assert.IsType(t, &GogsDownloader{}, got)
assert.EqualValues(t, tt.baseURL, got.(*GogsDownloader).baseURL)
assert.EqualValues(t, tt.repoOwner, got.(*GogsDownloader).repoOwner)
assert.EqualValues(t, tt.repoName, got.(*GogsDownloader).repoName)
})
}
}

View file

@ -6,6 +6,7 @@
{{if .RepoCount}}
<div class="ui small label">{{.RepoCount}}</div>
{{end}}
<span hidden test-name="repository-count">{{.RepoCount}}</span>
</a>
{{if .CanReadProjects}}
<a class="{{if .PageIsViewProjects}}active {{end}}item" href="{{$.Org.HomeLink}}/-/projects">
@ -13,6 +14,7 @@
{{if .ProjectCount}}
<div class="ui small label">{{.ProjectCount}}</div>
{{end}}
<span hidden test-name="project-count">{{.ProjectCount}}</span>
</a>
{{end}}
{{if and .IsPackageEnabled .CanReadPackages}}
@ -31,6 +33,7 @@
<div class="ui small label">{{.NumMembers}}</div>
</a>
{{end}}
<span hidden test-name="member-count">{{.NumMembers}}</span>
{{if .IsOrganizationMember}}
<a class="{{if $.PageIsOrgTeams}}active {{end}}item" href="{{$.OrgLink}}/teams">
{{svg "octicon-people"}} {{ctx.Locale.Tr "org.teams"}}
@ -39,6 +42,7 @@
{{end}}
</a>
{{end}}
<span hidden test-name="team-count">{{.NumTeams}}</span>
{{if .IsOrganizationOwner}}
<a id="settings-btn" class="{{if .PageIsOrgSettings}}active {{end}}right item" href="{{.OrgLink}}/settings">
{{svg "octicon-tools"}} {{ctx.Locale.Tr "repo.settings"}}

View file

@ -15,7 +15,7 @@
{{if .Title}}{{.Title}}{{else}}{{ctx.Locale.Tr "actions.runs.empty_commit_message"}}{{end}}
</a>
<div class="flex-item-body">
<b>{{if not $.CurWorkflow}}{{.WorkflowID}} {{end}}#{{.Index}}</b>:
<b>{{if not $.CurWorkflow}}{{.WorkflowID}} {{end}}#{{.Index}}</b> -
{{- if .ScheduleID -}}
{{ctx.Locale.Tr "actions.runs.scheduled"}}
{{- else -}}

View file

@ -10,6 +10,7 @@
{{if .RepoCount}}
<div class="ui small label">{{.RepoCount}}</div>
{{end}}
<span hidden test-name="repository-count">{{.RepoCount}}</span>
</a>
{{if or .ContextUser.IsIndividual .CanReadProjects}}
<a href="{{.ContextUser.HomeLink}}/-/projects" class="{{if .PageIsViewProjects}}active {{end}}item">
@ -17,6 +18,7 @@
{{if .ProjectCount}}
<div class="ui small label">{{.ProjectCount}}</div>
{{end}}
<span hidden test-name="project-count">{{.ProjectCount}}</span>
</a>
{{end}}
{{if and .IsPackageEnabled (or .ContextUser.IsIndividual .CanReadPackages)}}

View file

@ -59,7 +59,7 @@
</div>
<div class="field {{if .Err_RedirectURI}}error{{end}}">
<label for="redirect-uris">{{ctx.Locale.Tr "settings.oauth2_redirect_uris"}}</label>
<textarea name="redirect_uris" id="redirect-uris"></textarea>
<textarea name="redirect_uris" id="redirect-uris" required></textarea>
</div>
<div class="field {{if .Err_ConfidentialClient}}error{{end}}">
<div class="ui checkbox">

View file

@ -8,6 +8,7 @@ import (
"io"
"net/http"
"net/url"
"regexp"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
@ -41,6 +42,16 @@ func TestAPIDownloadArchive(t *testing.T) {
assert.Len(t, bs, 266)
assert.EqualValues(t, "application/gzip", resp.Header().Get("Content-Type"))
// Must return a link to a commit ID as the "immutable" archive link
linkHeaderRe := regexp.MustCompile(`<(?P<url>https?://.*/api/v1/repos/user2/repo1/archive/[a-f0-9]+\.tar\.gz.*)>; rel="immutable"`)
m := linkHeaderRe.FindStringSubmatch(resp.Header().Get("Link"))
assert.NotEmpty(t, m[1])
resp = MakeRequest(t, NewRequest(t, "GET", m[1]).AddTokenAuth(token), http.StatusOK)
bs2, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
// The locked URL should give the same bytes as the non-locked one
assert.EqualValues(t, bs, bs2)
link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master.bundle", user2.Name, repo.Name))
resp = MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(token), http.StatusOK)
bs, err = io.ReadAll(resp.Body)

View file

@ -692,6 +692,7 @@ type DeclarativeRepoOptions struct {
DisabledUnits optional.Option[[]unit_model.Type]
Files optional.Option[[]*files_service.ChangeRepoFile]
WikiBranch optional.Option[string]
AutoInit optional.Option[bool]
}
func CreateDeclarativeRepoWithOptions(t *testing.T, owner *user_model.User, opts DeclarativeRepoOptions) (*repo_model.Repository, string, func()) {
@ -706,11 +707,18 @@ func CreateDeclarativeRepoWithOptions(t *testing.T, owner *user_model.User, opts
repoName = gouuid.NewString()
}
var autoInit bool
if opts.AutoInit.Has() {
autoInit = opts.AutoInit.Value()
} else {
autoInit = true
}
// Create the repository
repo, err := repo_service.CreateRepository(db.DefaultContext, owner, owner, repo_service.CreateRepoOptions{
Name: repoName,
Description: "Temporary Repo",
AutoInit: true,
AutoInit: autoInit,
Gitignores: "",
License: "WTFPL",
Readme: "Default",
@ -742,6 +750,7 @@ func CreateDeclarativeRepoWithOptions(t *testing.T, owner *user_model.User, opts
// Add files, if any.
var sha string
if opts.Files.Has() {
assert.True(t, autoInit, "Files cannot be specified if AutoInit is disabled")
files := opts.Files.Value()
resp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, owner, &files_service.ChangeRepoFilesOptions{

View file

@ -15,6 +15,7 @@ import (
"testing"
"time"
auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
@ -22,6 +23,7 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/indexer/issues"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/references"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
@ -193,6 +195,93 @@ func TestNewIssue(t *testing.T) {
testNewIssue(t, session, "user2", "repo1", "Title", "Description")
}
func TestIssueDependencies(t *testing.T) {
defer tests.PrepareTestEnv(t)()
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
session := loginUser(t, owner.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
repo, _, f := CreateDeclarativeRepoWithOptions(t, owner, DeclarativeRepoOptions{})
defer f()
createIssue := func(t *testing.T, title string) api.Issue {
t.Helper()
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues", owner.Name, repo.Name)
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateIssueOption{
Body: "",
Title: title,
}).AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusCreated)
var apiIssue api.Issue
DecodeJSON(t, resp, &apiIssue)
return apiIssue
}
addDependency := func(t *testing.T, issue, dependency api.Issue) {
t.Helper()
urlStr := fmt.Sprintf("/%s/%s/issues/%d/dependency/add", owner.Name, repo.Name, issue.Index)
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
"_csrf": GetCSRF(t, session, fmt.Sprintf("/%s/%s/issues/%d", owner.Name, repo.Name, issue.Index)),
"newDependency": fmt.Sprintf("%d", dependency.Index),
})
session.MakeRequest(t, req, http.StatusSeeOther)
}
removeDependency := func(t *testing.T, issue, dependency api.Issue) {
t.Helper()
urlStr := fmt.Sprintf("/%s/%s/issues/%d/dependency/delete", owner.Name, repo.Name, issue.Index)
req := NewRequestWithValues(t, "POST", urlStr, map[string]string{
"_csrf": GetCSRF(t, session, fmt.Sprintf("/%s/%s/issues/%d", owner.Name, repo.Name, issue.Index)),
"removeDependencyID": fmt.Sprintf("%d", dependency.Index),
"dependencyType": "blockedBy",
})
session.MakeRequest(t, req, http.StatusSeeOther)
}
assertHasDependency := func(t *testing.T, issueID, dependencyID int64, hasDependency bool) {
t.Helper()
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/dependencies", owner.Name, repo.Name, issueID)
req := NewRequest(t, "GET", urlStr)
resp := MakeRequest(t, req, http.StatusOK)
var issues []api.Issue
DecodeJSON(t, resp, &issues)
if hasDependency {
assert.NotEmpty(t, issues)
assert.EqualValues(t, issues[0].Index, dependencyID)
} else {
assert.Empty(t, issues)
}
}
t.Run("Add dependency", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
issue1 := createIssue(t, "issue #1")
issue2 := createIssue(t, "issue #2")
addDependency(t, issue1, issue2)
assertHasDependency(t, issue1.Index, issue2.Index, true)
})
t.Run("Remove dependency", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
issue1 := createIssue(t, "issue #1")
issue2 := createIssue(t, "issue #2")
addDependency(t, issue1, issue2)
removeDependency(t, issue1, issue2)
assertHasDependency(t, issue1.Index, issue2.Index, false)
})
}
func TestIssueCommentClose(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2")
@ -876,3 +965,23 @@ body:
})
})
}
func TestIssueUnsubscription(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
repo, _, f := CreateDeclarativeRepoWithOptions(t, user, DeclarativeRepoOptions{
AutoInit: optional.Some(false),
})
defer f()
session := loginUser(t, user.Name)
issueURL := testNewIssue(t, session, user.Name, repo.Name, "Issue title", "Description")
req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/watch", issueURL), map[string]string{
"_csrf": GetCSRF(t, session, issueURL),
"watch": "0",
})
session.MakeRequest(t, req, http.StatusOK)
})
}

View file

@ -0,0 +1,167 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"fmt"
"net/http"
"strconv"
"testing"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
project_model "code.gitea.io/gitea/models/project"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/tests"
"github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type userCountTest struct {
doer *user_model.User
user *user_model.User
session *TestSession
repoCount int64
projectCount int64
memberCount int64
teamCount int64
}
func (countTest *userCountTest) Init(t *testing.T, doerID, userID int64) {
countTest.doer = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doerID})
countTest.user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID})
countTest.session = loginUser(t, countTest.doer.Name)
var err error
countTest.repoCount, err = repo_model.CountRepository(db.DefaultContext, &repo_model.SearchRepoOptions{
Actor: countTest.doer,
OwnerID: countTest.user.ID,
Private: true,
Collaborate: optional.Some(false),
})
require.NoError(t, err)
var projectType project_model.Type
if countTest.user.IsOrganization() {
projectType = project_model.TypeOrganization
} else {
projectType = project_model.TypeIndividual
}
countTest.projectCount, err = db.Count[project_model.Project](db.DefaultContext, project_model.SearchOptions{
OwnerID: countTest.user.ID,
IsClosed: optional.Some(false),
Type: projectType,
})
require.NoError(t, err)
if !countTest.user.IsOrganization() {
return
}
org := (*organization.Organization)(countTest.user)
isMember, err := org.IsOrgMember(db.DefaultContext, countTest.doer.ID)
require.NoError(t, err)
countTest.memberCount, err = organization.CountOrgMembers(db.DefaultContext, &organization.FindOrgMembersOpts{
OrgID: org.ID,
PublicOnly: !isMember,
})
require.NoError(t, err)
teams, err := org.LoadTeams(db.DefaultContext)
require.NoError(t, err)
countTest.teamCount = int64(len(teams))
}
func (countTest *userCountTest) getCount(doc *goquery.Document, name string) (int64, error) {
selection := doc.Find(fmt.Sprintf("[test-name=\"%s\"]", name))
if selection.Length() != 1 {
return 0, fmt.Errorf("%s was not found", name)
}
return strconv.ParseInt(selection.Text(), 10, 64)
}
func (countTest *userCountTest) TestPage(t *testing.T, page string, orgLink bool) {
t.Run(page, func(t *testing.T) {
var userLink string
if orgLink {
userLink = countTest.user.OrganisationLink()
} else {
userLink = countTest.user.HomeLink()
}
req := NewRequestf(t, "GET", "%s/%s", userLink, page)
resp := countTest.session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
repoCount, err := countTest.getCount(htmlDoc.doc, "repository-count")
require.NoError(t, err)
assert.Equal(t, countTest.repoCount, repoCount)
projectCount, err := countTest.getCount(htmlDoc.doc, "project-count")
require.NoError(t, err)
assert.Equal(t, countTest.projectCount, projectCount)
if !countTest.user.IsOrganization() {
return
}
memberCount, err := countTest.getCount(htmlDoc.doc, "member-count")
require.NoError(t, err)
assert.Equal(t, countTest.memberCount, memberCount)
teamCount, err := countTest.getCount(htmlDoc.doc, "team-count")
require.NoError(t, err)
assert.Equal(t, countTest.teamCount, teamCount)
})
}
func TestFrontendHeaderCountUser(t *testing.T) {
defer tests.PrepareTestEnv(t)()
countTest := new(userCountTest)
countTest.Init(t, 2, 2)
countTest.TestPage(t, "", false)
countTest.TestPage(t, "?tab=repositories", false)
countTest.TestPage(t, "-/projects", false)
countTest.TestPage(t, "-/packages", false)
countTest.TestPage(t, "?tab=activity", false)
countTest.TestPage(t, "?tab=stars", false)
}
func TestFrontendHeaderCountOrg(t *testing.T) {
defer tests.PrepareTestEnv(t)()
countTest := new(userCountTest)
countTest.Init(t, 15, 17)
countTest.TestPage(t, "", false)
countTest.TestPage(t, "-/projects", false)
countTest.TestPage(t, "-/packages", false)
countTest.TestPage(t, "members", true)
countTest.TestPage(t, "teams", true)
countTest.TestPage(t, "settings", true)
countTest.TestPage(t, "settings/hooks", true)
countTest.TestPage(t, "settings/labels", true)
countTest.TestPage(t, "settings/applications", true)
countTest.TestPage(t, "settings/packages", true)
countTest.TestPage(t, "settings/actions/runners", true)
countTest.TestPage(t, "settings/actions/secrets", true)
countTest.TestPage(t, "settings/actions/variables", true)
countTest.TestPage(t, "settings/blocked_users", true)
countTest.TestPage(t, "settings/delete", true)
}

View file

@ -402,7 +402,7 @@ td .commit-summary {
.pdf-content {
width: 100%;
height: 600px;
height: 100vh;
border: none !important;
display: flex;
align-items: center;

View file

@ -141,6 +141,7 @@
/* other colors */
--color-gold: #b1983b;
--color-white: #ffffff;
--color-pure-black: #000000;
--color-diff-removed-word-bg: #783030;
--color-diff-added-word-bg: #255c39;
--color-diff-removed-row-bg: #432121;
@ -304,7 +305,7 @@ i.grey.icon.icon.icon.icon {
}
::selection {
background: var(--steel-100) !important;
color: var(--color-white) !important;
color: var(--color-pure-black) !important;
}
strong.attention-important, svg.attention-important {
color: var(--color-violet-light);