Compare commits

...

11 Commits

Author SHA1 Message Date
Lunny Xiao
377a0a20f0
Merge setting.InitXXX into one function with options (#24389)
This PR will merge 3 Init functions on setting packages as 1 and
introduce an options struct.
2023-05-04 11:55:35 +08:00
Yarden Shoham
a2fe68e50b
Changelog for 1.19.3 (#24495) (#24506)
Frontport #24495

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Co-authored-by: John Olheiser <john.olheiser@gmail.com>
2023-05-03 22:05:47 -04:00
techknowlogick
f7f0782132
Use Actions for DB & E2E tests (#24494)
following https://github.com/go-gitea/gitea/pull/24314 and
https://github.com/go-gitea/gitea/pull/24434, this PR moves drone cron
pipelines to (GitHub) Actions. As these are mostly compatible with Gitea
Actions, when we start to dogfood, these will already be migrated.

---------

Co-authored-by: silverwind <me@silverwind.io>
2023-05-04 02:04:02 +00:00
zeripath
ad8631c069
Fix intermittent CI failure in EmptyQueue (#23753)
The ordering of the final token causing a close of the queue in this
test may be out of sync due to concurrency. Instead just use ensure that
the queue is closed when everything expected is done.

Fixes: https://github.com/go-gitea/gitea/issues/23608
Fixes: https://github.com/go-gitea/gitea/issues/23977

---------

Signed-off-by: Andrew Thornton <art27@cantab.net>
Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
2023-05-03 21:37:30 -04:00
Jack Hay
402df1d6b4
Prevent a user with a different email from accepting the team invite (#24491)
## Changes
- Fixes the case where a logged in user can accept an email invitation
even if their email address does not match the address in the invitation
2023-05-03 21:21:58 -04:00
yp05327
dbb3736785
Fix incorrect webhook time and use relative-time to display it (#24477)
Fixes #24414
After click replay this webhook, it will display `now`

![image](https://user-images.githubusercontent.com/18380374/235559399-05a23927-13f5-442d-8f10-2c7cd24022a0.png)

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
2023-05-03 19:53:43 -04:00
silverwind
4a722c9a45
Make Issue/PR/projects more compact, misc CSS tweaks (#24459)
- Remove various horizontal dividers on repo pages that didn't provide
visual benefit
- Remove label/milestone pills on single issue/pr page
- Remove issue-related pill buttons on projects page
- Increase contrast of color-secondary on arc-green
- Improve notifications icon, make circle bigger
- Remove some inline styles
- Fix focus in issue/pr title edit and select all text on button click

### Issue and PR before and after

<img width="1249" alt="Screenshot 2023-05-01 at 11 44 22"
src="https://user-images.githubusercontent.com/115237/235436662-a708288e-84fb-4b2e-a5a2-3a1c17d28f6c.png">
<img width="1248" alt="Screenshot 2023-05-01 at 11 58 51"
src="https://user-images.githubusercontent.com/115237/235437992-f863e483-f3cc-4cc1-8204-fd223647a0c9.png">



### Projects before and after

<img width="1255" alt="Screenshot 2023-05-01 at 11 41 02"
src="https://user-images.githubusercontent.com/115237/235436433-0deb85d6-4e7d-4e74-847f-254cc70a0cf9.png">
<img width="1267" alt="Screenshot 2023-05-01 at 11 40 03"
src="https://user-images.githubusercontent.com/115237/235436431-715b13cb-f78c-4d86-b27a-9229f9738c5b.png">


### Releases before and after

<img width="1243" alt="Screenshot 2023-05-01 at 11 41 12"
src="https://user-images.githubusercontent.com/115237/235436457-b655ee6f-03b8-4595-8d8c-b15ea469e988.png">
<img width="1240" alt="Screenshot 2023-05-01 at 11 40 10"
src="https://user-images.githubusercontent.com/115237/235436456-05a2a0dd-7cbb-4f26-b0d3-4f667df4bb95.png">

### Misc

<img width="58" alt="Screenshot 2023-05-01 at 10 49 13"
src="https://user-images.githubusercontent.com/115237/235432494-936ce995-6e22-47bc-ab2d-c9e93d31987d.png">
<img width="57" alt="Screenshot 2023-05-01 at 18 57 08"
src="https://user-images.githubusercontent.com/115237/235492430-1d32cfe0-0f2c-467c-b2fa-925b27e30e0e.png">


Issue title edit and wrap:

<img width="1238" alt="Screenshot 2023-05-01 at 12 34 40"
src="https://user-images.githubusercontent.com/115237/235441407-d5067a57-e586-4865-a652-282e5944abb4.png">
<img width="1232" alt="Screenshot 2023-05-01 at 12 06 24"
src="https://user-images.githubusercontent.com/115237/235438710-1a543dda-220f-4d87-8f93-f1710c0695f0.png">

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2023-05-03 17:58:59 -04:00
KN4CK3R
723598b803
Implement Cargo HTTP index (#24452)
This implements the HTTP index
[RFC](https://rust-lang.github.io/rfcs/2789-sparse-index.html) for Cargo
registries.

Currently this is a preview feature and you need to use the nightly of
`cargo`:

`cargo +nightly -Z sparse-registry update`

See https://github.com/rust-lang/cargo/issues/9069 for more information.

---------

Co-authored-by: Giteabot <teabot@gitea.io>
2023-05-03 16:58:43 -04:00
wxiaoguang
48e3e38ee0
Clean up polluted styles and remove dead CSS code (#24497)
Follow #24393


The funny history:

* At the beginning, `.ui.message` was polluted by `text-align: center`
* Then people do `<div class="ui ... message text left">`
* But `.ui.left` is polluted by `float: left`
* Then people do `#xxx .ui.message { width: 100% !important;}`

The code just becomes more and more hacky.

After removing the pollution,  everything becomes clear and straight.


And, this PR also does:

1. Remove the `package.css`, its styles could be provided by `top
aligned`
2. Remove `#avatar-arrow`, dead code



Screenshot:


![image](https://user-images.githubusercontent.com/2114189/235862130-a9eb5d8f-7d01-457c-99f7-21d0abc3075e.png)


![image](https://user-images.githubusercontent.com/2114189/235862222-139709a7-95c2-4f89-a40f-100b2d76d9bb.png)

Co-authored-by: Giteabot <teabot@gitea.io>
2023-05-03 14:32:10 -04:00
Lunny Xiao
e9b39250b2
Improve pull request merge box when pull request merged and branch deleted. (#24397)
This PR hide the pull request merge box totally if it's merged and branch deleted.

It's also add a bold for merge base commit id in merged message comment

Before:

<img width="989" alt="图片"
src="https://user-images.githubusercontent.com/81045/235066590-28deb506-e824-4a42-a9a2-791cd136756e.png">

After:

<img width="1030" alt="图片"
src="https://user-images.githubusercontent.com/81045/235080749-11d5efe8-a06e-4528-a75f-f6c6d191db50.png">

---------

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2023-05-03 21:52:19 +08:00
silverwind
a9ed87ce4a
Fix EasyMDE toolbar (#24489)
Fixes https://github.com/go-gitea/gitea/issues/24486

The "clean block" button is gone because I could not find a matching
octicon. Order of buttons is roughly equal to textarea.

<img width="824" alt="Screenshot 2023-05-02 at 21 10 00"
src="https://user-images.githubusercontent.com/115237/235762593-ceccb260-e665-4932-ac8a-ef6fe8406a3c.png">

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2023-05-03 01:23:39 -04:00
98 changed files with 1311 additions and 1574 deletions

View File

@ -1,749 +1,3 @@
---
kind: pipeline
type: docker
name: compliance
platform:
os: linux
arch: amd64
trigger:
event:
- pull_request
paths:
exclude:
- "docs/**"
- "*.md"
volumes:
- name: deps
temp: {}
steps:
- name: deps-frontend
image: node:18
pull: always
commands:
- make deps-frontend
- name: deps-backend
image: gitea/test_env:linux-1.20-amd64
pull: always
commands:
- make deps-backend
- make deps-tools
volumes:
- name: deps
path: /go
- name: lint-frontend
image: node:18
commands:
- make lint-frontend
depends_on: [deps-frontend]
- name: lint-backend
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
pull: always
commands:
- make lint-backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata sqlite sqlite_unlock_notify
depends_on: [deps-backend]
volumes:
- name: deps
path: /go
- name: lint-backend-windows
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
commands:
- make lint-go-windows lint-go-vet
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata sqlite sqlite_unlock_notify
GOOS: windows
GOARCH: amd64
depends_on: [deps-backend]
volumes:
- name: deps
path: /go
- name: lint-backend-gogit
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
commands:
- make lint-backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata gogit sqlite sqlite_unlock_notify
depends_on: [deps-backend]
volumes:
- name: deps
path: /go
- name: checks-frontend
image: node:18
commands:
- make checks-frontend
depends_on: [deps-frontend]
- name: checks-backend
image: gitea/test_env:linux-1.20-amd64
commands:
- make --always-make checks-backend # ensure the 'go-licenses' make target runs
depends_on: [deps-backend]
volumes:
- name: deps
path: /go
- name: test-frontend
image: node:18
commands:
- make test-frontend
depends_on: [lint-frontend]
- name: build-frontend
image: node:18
commands:
- make frontend
depends_on: [deps-frontend]
- name: build-backend-no-gcc
image: gitea/test_env:linux-1.19-amd64 # this step is kept as the lowest version of golang that we support
pull: always
environment:
GOPROXY: https://goproxy.io
commands:
- go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
- name: build-backend-arm64
image: gitea/test_env:linux-1.20-amd64
environment:
GOPROXY: https://goproxy.io
GOOS: linux
GOARCH: arm64
TAGS: bindata gogit
commands:
- make backend # test cross compile
- rm ./gitea # clean
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
- name: build-backend-windows
image: gitea/test_env:linux-1.20-amd64
environment:
GOPROXY: https://goproxy.io
GOOS: windows
GOARCH: amd64
TAGS: bindata gogit
commands:
- go build -o gitea_windows
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
- name: build-backend-386
image: gitea/test_env:linux-1.20-amd64
environment:
GOPROXY: https://goproxy.io
GOOS: linux
GOARCH: 386
commands:
- go build -o gitea_linux_386 # test if compatible with 32 bit
depends_on: [deps-backend, checks-backend]
volumes:
- name: deps
path: /go
---
kind: pipeline
type: docker
name: testing-pgsql
platform:
os: linux
arch: amd64
depends_on:
- compliance
trigger:
event:
- pull_request
paths:
exclude:
- "docs/**"
volumes:
- name: deps
temp: {}
services:
- name: pgsql
pull: default
image: postgres:15
environment:
POSTGRES_DB: test
POSTGRES_PASSWORD: postgres
- name: ldap
image: gitea/test-openldap:latest
pull: always
- name: minio
image: minio/minio:RELEASE.2021-03-12T00-00-47Z
pull: always
commands:
- minio server /data
environment:
MINIO_ACCESS_KEY: 123456
MINIO_SECRET_KEY: 12345678
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
when:
event:
exclude:
- pull_request
- name: deps-backend
image: gitea/test_env:linux-1.20-amd64
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: prepare-test-env
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
pull: always
commands:
- ./build/test-env-prepare.sh
- name: build
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- ./build/test-env-check.sh
- make backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: test-pgsql
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- timeout -s ABRT 50m make test-pgsql-migration test-pgsql
environment:
GOPROXY: https://goproxy.io
TAGS: bindata gogit
RACE_ENABLED: true
TEST_TAGS: gogit
TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
depends_on: [build]
volumes:
- name: deps
path: /go
---
kind: pipeline
type: docker
name: testing-mysql
platform:
os: linux
arch: amd64
depends_on:
- compliance
trigger:
event:
- pull_request
paths:
exclude:
- "docs/**"
volumes:
- name: deps
temp: {}
services:
- name: mysql
image: mysql:5.7
pull: always
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: test
- name: elasticsearch
image: elasticsearch:7.5.0
pull: always
environment:
discovery.type: single-node
- name: smtpimap
image: tabascoterrier/docker-imap-devel:latest
pull: always
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
when:
event:
exclude:
- pull_request
- name: deps-backend
image: gitea/test_env:linux-1.20-amd64
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: prepare-test-env
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
pull: always
commands:
- ./build/test-env-prepare.sh
- name: build
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- ./build/test-env-check.sh
- make backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: unit-test
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- make unit-test-coverage test-check
environment:
GOPROXY: https://goproxy.io
TAGS: bindata
RACE_ENABLED: true
GITHUB_READ_TOKEN:
from_secret: github_read_token
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: unit-test-gogit
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- make unit-test-coverage test-check
environment:
GOPROXY: https://goproxy.io
TAGS: bindata gogit
RACE_ENABLED: true
GITHUB_READ_TOKEN:
from_secret: github_read_token
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: test-mysql
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- make test-mysql-migration integration-test-coverage
environment:
GOPROXY: https://goproxy.io
TAGS: bindata
RACE_ENABLED: true
USE_REPO_TEST_DIR: 1
TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
depends_on: [build]
volumes:
- name: deps
path: /go
- name: generate-coverage
image: gitea/test_env:linux-1.20-amd64
commands:
- make coverage
environment:
GOPROXY: https://goproxy.io
TAGS: bindata
depends_on: [unit-test, test-mysql]
when:
branch:
- main
event:
- push
- pull_request
- name: coverage-codecov
image: woodpeckerci/plugin-codecov:next-alpine
pull: always
settings:
files:
- coverage.all
token:
from_secret: codecov_token
depends_on: [generate-coverage]
when:
branch:
- main
event:
- push
- pull_request
---
kind: pipeline
type: docker
name: testing-mysql8
platform:
os: linux
arch: amd64
depends_on:
- compliance
trigger:
event:
- pull_request
paths:
exclude:
- "docs/**"
volumes:
- name: deps
temp: {}
services:
- name: mysql8
image: mysql:8
pull: always
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: testgitea
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
when:
event:
exclude:
- pull_request
- name: deps-backend
image: gitea/test_env:linux-1.20-amd64
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: prepare-test-env
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
pull: always
commands:
- ./build/test-env-prepare.sh
- name: build
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- ./build/test-env-check.sh
- make backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: test-mysql8
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- timeout -s ABRT 50m make test-mysql8-migration test-mysql8
environment:
GOPROXY: https://goproxy.io
TAGS: bindata
USE_REPO_TEST_DIR: 1
depends_on: [build]
volumes:
- name: deps
path: /go
---
kind: pipeline
type: docker
name: testing-mssql
platform:
os: linux
arch: amd64
depends_on:
- compliance
trigger:
event:
- pull_request
paths:
exclude:
- "docs/**"
volumes:
- name: deps
temp: {}
services:
- name: mssql
image: mcr.microsoft.com/mssql/server:latest
pull: always
environment:
ACCEPT_EULA: Y
MSSQL_PID: Standard
SA_PASSWORD: MwantsaSecurePassword1
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
when:
event:
exclude:
- pull_request
- name: deps-backend
image: gitea/test_env:linux-1.20-amd64
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: prepare-test-env
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
pull: always
commands:
- ./build/test-env-prepare.sh
- name: build
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- ./build/test-env-check.sh
- make backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: test-mssql
image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- make test-mssql-migration test-mssql
environment:
GOPROXY: https://goproxy.io
TAGS: bindata
USE_REPO_TEST_DIR: 1
depends_on: [build]
volumes:
- name: deps
path: /go
---
kind: pipeline
name: testing-sqlite
platform:
os: linux
arch: arm64
depends_on:
- compliance
trigger:
event:
- pull_request
paths:
exclude:
- "docs/**"
volumes:
- name: deps
temp: {}
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
when:
event:
exclude:
- pull_request
- name: deps-backend
image: gitea/test_env:linux-1.20-arm64
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: prepare-test-env
image: gitea/test_env:linux-1.20-arm64 # https://gitea.com/gitea/test-env
pull: always
commands:
- ./build/test-env-prepare.sh
- name: build
image: gitea/test_env:linux-1.20-arm64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- ./build/test-env-check.sh
- make backend
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata gogit sqlite sqlite_unlock_notify
depends_on: [deps-backend, prepare-test-env]
volumes:
- name: deps
path: /go
- name: test-sqlite
image: gitea/test_env:linux-1.20-arm64 # https://gitea.com/gitea/test-env
user: gitea
commands:
- timeout -s ABRT 50m make test-sqlite-migration test-sqlite
environment:
GOPROXY: https://goproxy.io
TAGS: bindata gogit sqlite sqlite_unlock_notify
RACE_ENABLED: true
TEST_TAGS: gogit sqlite sqlite_unlock_notify
USE_REPO_TEST_DIR: 1
depends_on: [build]
volumes:
- name: deps
path: /go
---
kind: pipeline
type: docker
name: testing-e2e
platform:
os: linux
arch: amd64
depends_on:
- compliance
trigger:
event:
- pull_request
paths:
exclude:
- "docs/**"
volumes:
- name: deps
temp: {}
steps:
- name: deps-frontend
image: node:18
pull: always
commands:
- make deps-frontend
- name: build-frontend
image: node:18
commands:
- make frontend
depends_on: [deps-frontend]
- name: deps-backend
image: gitea/test_env:linux-1.20-amd64
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
# TODO: We should probably build all dependencies into a test image
- name: test-e2e
image: mcr.microsoft.com/playwright:v1.32.3-focal
commands:
- apt-get -qq update && apt-get -qqy install jq build-essential
- curl -fsSL "https://go.dev/dl/$(curl -s 'https://go.dev/dl/?mode=json' | jq -r '.[].version' | sort -Vr | head -1).linux-amd64.tar.gz" | tar -xz -C /usr/local
- groupadd --gid 1001 gitea && useradd -m --gid 1001 --uid 1001 gitea
- ./build/test-env-prepare.sh
- su gitea bash -c "export PATH=$PATH:/usr/local/go/bin && timeout -s ABRT 40m make test-e2e-sqlite"
environment:
GOPROXY: https://goproxy.io
GOSUMDB: sum.golang.org
USE_REPO_TEST_DIR: 1
DEBIAN_FRONTEND: noninteractive
depends_on: [build-frontend, deps-backend]
volumes:
- name: deps
path: /go
---
kind: pipeline
type: docker
@ -767,13 +21,6 @@ trigger:
exclude:
- "docs/**"
depends_on:
- testing-mysql
- testing-mysql8
- testing-mssql
- testing-pgsql
- testing-sqlite
volumes:
- name: deps
temp: {}
@ -902,13 +149,6 @@ trigger:
event:
- tag
depends_on:
- testing-mysql
- testing-mysql8
- testing-mssql
- testing-pgsql
- testing-sqlite
volumes:
- name: deps
temp: {}
@ -1013,22 +253,12 @@ platform:
os: linux
arch: amd64
depends_on:
- testing-mysql
- testing-mysql8
- testing-mssql
- testing-pgsql
- testing-sqlite
trigger:
ref:
include:
- "refs/tags/**"
exclude:
- "refs/tags/**-rc*"
event:
exclude:
- cron
paths:
exclude:
- "docs/**"
@ -1093,19 +323,9 @@ platform:
os: linux
arch: amd64
depends_on:
- testing-mysql
- testing-mysql8
- testing-mssql
- testing-pgsql
- testing-sqlite
trigger:
ref:
- "refs/tags/**-rc*"
event:
exclude:
- cron
paths:
exclude:
- "docs/**"
@ -1168,19 +388,9 @@ platform:
os: linux
arch: amd64
depends_on:
- testing-mysql
- testing-mysql8
- testing-mssql
- testing-pgsql
- testing-sqlite
trigger:
ref:
- refs/heads/main
event:
exclude:
- cron
steps:
- name: fetch-tags
@ -1241,19 +451,9 @@ platform:
os: linux
arch: amd64
depends_on:
- testing-mysql
- testing-mysql8
- testing-mssql
- testing-pgsql
- testing-sqlite
trigger:
ref:
- "refs/heads/release/v*"
event:
exclude:
- cron
steps:
- name: fetch-tags
@ -1315,22 +515,12 @@ platform:
os: linux
arch: arm64
depends_on:
- testing-mysql
- testing-mysql8
- testing-mssql
- testing-pgsql
- testing-sqlite
trigger:
ref:
include:
- "refs/tags/**"
exclude:
- "refs/tags/**-rc*"
event:
exclude:
- cron
paths:
exclude:
- "docs/**"
@ -1395,19 +585,9 @@ platform:
os: linux
arch: arm64
depends_on:
- testing-mysql
- testing-mysql8
- testing-mssql
- testing-pgsql
- testing-sqlite
trigger:
ref:
- "refs/tags/**-rc*"
event:
exclude:
- cron
paths:
exclude:
- "docs/**"
@ -1470,19 +650,9 @@ platform:
os: linux
arch: arm64
depends_on:
- testing-mysql
- testing-mysql8
- testing-mssql
- testing-pgsql
- testing-sqlite
trigger:
ref:
- refs/heads/main
event:
exclude:
- cron
paths:
exclude:
- "docs/**"
@ -1546,19 +716,9 @@ platform:
os: linux
arch: arm64
depends_on:
- testing-mysql
- testing-mysql8
- testing-mssql
- testing-pgsql
- testing-sqlite
trigger:
ref:
- "refs/heads/release/v*"
event:
exclude:
- cron
steps:
- name: fetch-tags
@ -1647,9 +807,6 @@ steps:
trigger:
ref:
- "refs/tags/**"
event:
exclude:
- cron
paths:
exclude:
- "docs/**"
@ -1697,9 +854,6 @@ trigger:
ref:
- refs/heads/main
- "refs/heads/release/v*"
event:
exclude:
- cron
paths:
exclude:
- "docs/**"

View File

@ -1,10 +1,10 @@
name: "Cron: Update licenses and gitignores"
on:
schedule:
# weekly on Monday at 0:07 UTC
- cron: "7 0 * * 1"
name: Update licenses and gitignores
jobs:
cron:
runs-on: ubuntu-latest

View File

@ -1,9 +1,9 @@
name: "Cron: Pull translations from Crowdin"
on:
schedule:
- cron: "7 0 * * *" # every day at 0:07 UTC
name: Pull translations from Crowdin
jobs:
crowdin_pull:
runs-on: ubuntu-latest

133
.github/workflows/pull-compliance.yml vendored Normal file
View File

@ -0,0 +1,133 @@
name: "Pull: Compliance Tests"
on: [pull_request]
jobs:
lint_basic:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20'
- name: deps-backend
run: make deps-backend deps-tools
- name: lint backend
run: make lint-backend
env:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata sqlite sqlite_unlock_notify
lint_windows:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20'
- name: deps-backend
run: make deps-backend deps-tools
- name: lint-backend-windows
run: make lint-go-windows lint-go-vet
env:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata sqlite sqlite_unlock_notify
GOOS: windows
GOARCH: amd64
lint_gogit:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20'
- name: deps-backend
run: make deps-backend deps-tools
- name: lint-backend-gogit
run: make lint-backend
env:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
GOSUMDB: sum.golang.org
TAGS: bindata gogit sqlite sqlite_unlock_notify
- name: checks backend
run: make --always-make checks-backend # ensure the 'go-licenses' make target runs
check_backend:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20'
- name: deps-backend
run: make deps-backend deps-tools
- name: checks backend
run: make --always-make checks-backend # ensure the 'go-licenses' make target runs
frontend:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup node
uses: actions/setup-node@v3
with:
node-version: 18
- name: deps-frontend
run: make deps-frontend
- name: lint frontend
run: make lint-frontend
- name: checks frontend
run: make checks-frontend
- name: test frontend
run: make test-frontend
backend:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20'
- name: setup node
uses: actions/setup-node@v3
with:
node-version: 18
- name: deps-backend
run: make deps-backend deps-tools
- name: deps-frontend
run: make deps-frontend
- name: build frontend
run: make frontend
- name: build-backend-no-gcc
run: go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
env:
GOPROXY: https://goproxy.io
- name: build-backend-arm64
run: make backend # test cross compile
env:
GOPROXY: https://goproxy.io
GOOS: linux
GOARCH: arm64
TAGS: bindata gogit
- name: build-backend-windows
run: go build -o gitea_windows
env:
GOPROXY: https://goproxy.io
GOOS: windows
GOARCH: amd64
TAGS: bindata gogit
- name: build-backend-386
run: go build -o gitea_linux_386 # test if compatible with 32 bit
env:
GOPROXY: https://goproxy.io
GOOS: linux
GOARCH: 386

View File

@ -1,4 +1,4 @@
name: Compliance testing for documentation
name: "Pull: Compliance testing for documentation"
on:
pull_request:

260
.github/workflows/pull-db_test.yml vendored Normal file
View File

@ -0,0 +1,260 @@
name: "Pull: Database Tests"
on: [pull_request]
jobs:
# PostgreSQL Tests
db_pgsql_test:
runs-on: ubuntu-latest
services:
pgsql:
image: postgres:15
env:
POSTGRES_DB: test
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
ldap:
image: gitea/test-openldap:latest
ports:
- "389:389"
- "636:636"
minio:
# as github actions doesn't support "entrypoint", we need to use a non-official image
# that has a custom entrypoint set to "minio server /data"
image: bitnami/minio:2021.3.17
env:
MINIO_ACCESS_KEY: 123456
MINIO_SECRET_KEY: 12345678
ports:
- "9000:9000"
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20.0'
- name: Add hosts to /etc/hosts
run: echo "127.0.0.1 pgsql ldap minio" | sudo tee -a /etc/hosts
- name: install dependencies
run: make deps-backend
- name: build
run: make backend
env:
GOPROXY: https://goproxy.io
GOSUMDB: sum.golang.org
TAGS: bindata
- name: run tests
run: timeout -s ABRT 50m make test-pgsql-migration test-pgsql
env:
GOPROXY: https://goproxy.io
TAGS: bindata gogit
RACE_ENABLED: true
TEST_TAGS: gogit
TEST_LDAP: 1
USE_REPO_TEST_DIR: 1
# SQLite Tests
db_sqlite_test:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20.0'
- name: install dependencies
run: make deps-backend
- name: build
run: make backend
env:
GOPROXY: https://goproxy.io
GOSUMDB: sum.golang.org
TAGS: bindata gogit sqlite sqlite_unlock_notify
- name: run tests
run: timeout -s ABRT 50m make test-sqlite-migration test-sqlite
env:
GOPROXY: https://goproxy.io
TAGS: bindata gogit sqlite sqlite_unlock_notify
RACE_ENABLED: true
TEST_TAGS: gogit sqlite sqlite_unlock_notify
USE_REPO_TEST_DIR: 1
# Unit Tests
db_unit_tests:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:5.7
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: test
ports:
- "3306:3306"
elasticsearch:
image: elasticsearch:7.5.0
env:
discovery.type: single-node
ports:
- "9200:9200"
smtpimap:
image: tabascoterrier/docker-imap-devel:latest
ports:
- "25:25"
- "143:143"
- "587:587"
- "993:993"
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20.0'
- name: Add hosts to /etc/hosts
run: echo "127.0.0.1 mysql elasticsearch smtpimap" | sudo tee -a /etc/hosts
- name: install dependencies
run: make deps-backend
- name: build
run: make backend
env:
GOPROXY: https://goproxy.io
GOSUMDB: sum.golang.org
TAGS: bindata
- name: unit tests
run: make unit-test-coverage test-check
env:
GOPROXY: https://goproxy.io
TAGS: bindata
RACE_ENABLED: true
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
- name: unit tests (gogit)
run: make unit-test-coverage test-check
env:
GOPROXY: https://goproxy.io
TAGS: bindata gogit
RACE_ENABLED: true
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
# MySQL Tests
db_mysql_test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:5.7
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: test
ports:
- "3306:3306"
elasticsearch:
image: elasticsearch:7.5.0
env:
discovery.type: single-node
ports:
- "9200:9200"
smtpimap:
image: tabascoterrier/docker-imap-devel:latest
ports:
- "25:25"
- "143:143"
- "587:587"
- "993:993"
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20.0'
- name: Add hosts to /etc/hosts
run: echo "127.0.0.1 mysql elasticsearch smtpimap" | sudo tee -a /etc/hosts
- name: install dependencies
run: make deps-backend
- name: build
run: make backend
env:
GOPROXY: https://goproxy.io
GOSUMDB: sum.golang.org
TAGS: bindata
- name: run tests
run: make test-mysql-migration integration-test-coverage
env:
GOPROXY: https://goproxy.io
TAGS: bindata
RACE_ENABLED: true
USE_REPO_TEST_DIR: 1
TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
# MySQL8 Tests
db_mysql8_test:
runs-on: ubuntu-latest
services:
mysql8:
image: mysql:8
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: testgitea
ports:
- "3306:3306"
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20.0'
- name: Add hosts to /etc/hosts
run: echo "127.0.0.1 mysql8" | sudo tee -a /etc/hosts
- name: install dependencies
run: make deps-backend
- name: build
run: make backend
env:
GOPROXY: https://goproxy.io
GOSUMDB: sum.golang.org
TAGS: bindata
- name: run tests
run: timeout -s ABRT 50m make test-mysql8-migration test-mysql8
env:
GOPROXY: https://goproxy.io
TAGS: bindata
USE_REPO_TEST_DIR: 1
# MSSQL Tests
db_mssql_test:
runs-on: ubuntu-latest
services:
mssql:
image: mcr.microsoft.com/mssql/server:latest
env:
ACCEPT_EULA: Y
MSSQL_PID: Standard
SA_PASSWORD: MwantsaSecurePassword1
ports:
- "1433:1433"
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20.0'
- name: Add hosts to /etc/hosts
run: echo "127.0.0.1 mssql" | sudo tee -a /etc/hosts
- name: install dependencies
run: make deps-backend
- name: build
run: make backend
env:
GOPROXY: https://goproxy.io
GOSUMDB: sum.golang.org
TAGS: bindata
- name: run tests
run: timeout -s ABRT 50m make test-mssql-migration test-mssql
env:
GOPROXY: https://goproxy.io
TAGS: bindata
USE_REPO_TEST_DIR: 1

View File

@ -1,4 +1,4 @@
name: Docker build dry run
name: "Pull: Docker Dry Run"
on: [pull_request]

28
.github/workflows/pull-e2e.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: "Pull: E2E Tests"
on: [pull_request]
jobs:
e2e_tests:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.20'
- name: setup node
uses: actions/setup-node@v3
with:
node-version: 18
- name: build
run: make deps-frontend frontend deps-backend
- name: Install playwright browsers
run: npx playwright install --with-deps
- name: run tests
run: timeout -s ABRT 40m make test-e2e-sqlite
env:
GOPROXY: https://goproxy.io
GOSUMDB: sum.golang.org
USE_REPO_TEST_DIR: 1

View File

@ -1,4 +1,4 @@
name: Publish documentation
name: "Docs: Publish"
on:
push:

View File

@ -4,6 +4,19 @@ This changelog goes through all the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.io).
## [1.19.3](https://github.com/go-gitea/gitea/releases/tag/1.19.3) - 2023-05-03
* SECURITY
* Use golang 1.20.4 to fix CVE-2023-24539, CVE-2023-24540, and CVE-2023-29400
* ENHANCEMENTS
* Enable whitespace rendering on selection in Monaco (#24444) (#24485)
* Improve milestone filter on issues page (#22423) (#24440)
* BUGFIXES
* Fix api error message if fork exists (#24487) (#24493)
* Fix user-cards format (#24428) (#24431)
* Fix incorrect CurrentUser check for docker rootless (#24435)
* Getting the tag list does not require being signed in (#24413) (#24416)
## [1.19.2](https://github.com/go-gitea/gitea/releases/tag/1.19.2) - 2023-04-26
* SECURITY

View File

@ -42,8 +42,7 @@ func runGenerateActionsRunnerToken(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
scope := c.String("scope")

View File

@ -57,8 +57,7 @@ func confirm() (bool, error) {
}
func initDB(ctx context.Context) error {
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
setting.LoadDBSetting()
setting.InitSQLLog(false)

View File

@ -87,8 +87,7 @@ func runRecreateTable(ctx *cli.Context) error {
golog.SetPrefix("")
golog.SetOutput(log.NewLoggerAsWriter("INFO", log.GetLogger(log.DEFAULT)))
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
setting.LoadDBSetting()
setting.Log.EnableXORMLog = ctx.Bool("debug")

View File

@ -185,8 +185,7 @@ func runDump(ctx *cli.Context) error {
}
fileName += "." + outType
}
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
// make sure we are logging to the console no matter what the configuration tells us do to
// FIXME: don't use CfgProvider directly

View File

@ -106,8 +106,9 @@ func initEmbeddedExtractor(c *cli.Context) error {
log.DelNamedLogger(log.DEFAULT)
// Read configuration file
setting.InitProviderAllowEmpty()
setting.LoadCommonSettings()
setting.Init(&setting.Options{
AllowEmpty: true,
})
patterns, err := compileCollectPatterns(c.Args())
if err != nil {

View File

@ -16,8 +16,7 @@ func runSendMail(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
if err := argsSet(c, "title"); err != nil {
return err

View File

@ -7,14 +7,8 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/setting"
)
func init() {
setting.SetCustomPathAndConf("", "", "")
setting.InitProviderAndLoadCommonSettingsForTest()
}
func TestMain(m *testing.M) {
unittest.MainTest(m, &unittest.TestOptions{
GiteaRootPath: "..",

View File

@ -51,8 +51,7 @@ func runRestoreRepository(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
var units []string
if s := c.String("units"); s != "" {
units = strings.Split(s, ",")

View File

@ -62,8 +62,7 @@ func setup(ctx context.Context, debug bool) {
} else {
_ = log.NewLogger(1000, "console", "console", `{"level":"fatal","stacktracelevel":"NONE","stderr":true}`)
}
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
if debug {
setting.RunMode = "dev"
}

View File

@ -177,8 +177,7 @@ func runWeb(ctx *cli.Context) error {
log.Info("Global init")
// Perform global initialization
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
routers.GlobalInitInstalled(graceful.GetManager().HammerContext())
// We check that AppDataPath exists here (it should have been created during installation)

View File

@ -8,14 +8,8 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/setting"
)
func init() {
setting.SetCustomPathAndConf("", "", "")
setting.InitProviderAndLoadCommonSettingsForTest()
}
func TestMain(m *testing.M) {
unittest.MainTest(m, &unittest.TestOptions{
GiteaRootPath: filepath.Join("..", ".."),

View File

@ -8,14 +8,8 @@ import (
"testing"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/setting"
)
func init() {
setting.SetCustomPathAndConf("", "", "")
setting.InitProviderAndLoadCommonSettingsForTest()
}
func TestMain(m *testing.M) {
unittest.MainTest(m, &unittest.TestOptions{
GiteaRootPath: filepath.Join("..", ".."),

View File

@ -9,7 +9,6 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/setting"
_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/repo"
@ -18,11 +17,6 @@ import (
"github.com/stretchr/testify/assert"
)
func init() {
setting.SetCustomPathAndConf("", "", "")
setting.InitProviderAndLoadCommonSettingsForTest()
}
func TestFixturesAreConsistent(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
unittest.CheckConsistencyFor(t,

View File

@ -11,18 +11,12 @@ import (
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/setting"
_ "code.gitea.io/gitea/models/system"
"github.com/stretchr/testify/assert"
)
func init() {
setting.SetCustomPathAndConf("", "", "")
setting.InitProviderAndLoadCommonSettingsForTest()
}
// TestFixturesAreConsistent assert that test fixtures are consistent
func TestFixturesAreConsistent(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

View File

@ -150,7 +150,7 @@ func MainTest(m *testing.M) {
setting.AppDataPath = tmpDataPath
setting.SetCustomPathAndConf("", "", "")
setting.InitProviderAndLoadCommonSettingsForTest()
unittest.InitSettings()
if err = git.InitFull(context.Background()); err != nil {
fmt.Printf("Unable to InitFull: %v\n", err)
os.Exit(1)

View File

@ -6,12 +6,15 @@ package unittest
import (
"context"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"testing"
"code.gitea.io/gitea/models/db"
system_model "code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/modules/auth/password/hash"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/setting"
@ -39,6 +42,22 @@ func fatalTestError(fmtStr string, args ...interface{}) {
os.Exit(1)
}
// InitSettings initializes config provider and load common setttings for tests
func InitSettings(extraConfigs ...string) {
setting.Init(&setting.Options{
AllowEmpty: true,
ExtraConfig: strings.Join(extraConfigs, "\n"),
})
if err := setting.PrepareAppDataPath(); err != nil {
log.Fatalf("Can not prepare APP_DATA_PATH: %v", err)
}
// register the dummy hash algorithm function used in the test fixtures
_ = hash.Register("dummy", hash.NewDummyHasher)
setting.PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
}
// TestOptions represents test options
type TestOptions struct {
GiteaRootPath string
@ -50,6 +69,9 @@ type TestOptions struct {
// MainTest a reusable TestMain(..) function for unit tests that need to use a
// test database. Creates the test database, and sets necessary settings.
func MainTest(m *testing.M, testOpts *TestOptions) {
setting.SetCustomPathAndConf("", "", "")
InitSettings()
var err error
giteaRoot = testOpts.GiteaRootPath

View File

@ -12,6 +12,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
webhook_module "code.gitea.io/gitea/modules/webhook"
gouuid "github.com/google/uuid"
@ -40,15 +41,14 @@ type HookResponse struct {
// HookTask represents a hook task.
type HookTask struct {
ID int64 `xorm:"pk autoincr"`
HookID int64 `xorm:"index"`
UUID string `xorm:"unique"`
api.Payloader `xorm:"-"`
PayloadContent string `xorm:"LONGTEXT"`
EventType webhook_module.HookEventType
IsDelivered bool
Delivered int64
DeliveredString string `xorm:"-"`
ID int64 `xorm:"pk autoincr"`
HookID int64 `xorm:"index"`
UUID string `xorm:"unique"`
api.Payloader `xorm:"-"`
PayloadContent string `xorm:"LONGTEXT"`
EventType webhook_module.HookEventType
IsDelivered bool
Delivered timeutil.TimeStampNano
// History info.
IsSucceed bool
@ -75,8 +75,6 @@ func (t *HookTask) BeforeUpdate() {
// AfterLoad updates the webhook object upon setting a column
func (t *HookTask) AfterLoad() {
t.DeliveredString = time.Unix(0, t.Delivered).Format("2006-01-02 15:04:05 MST")
if len(t.RequestContent) == 0 {
return
}
@ -115,12 +113,17 @@ func HookTasks(hookID int64, page int) ([]*HookTask, error) {
// CreateHookTask creates a new hook task,
// it handles conversion from Payload to PayloadContent.
func CreateHookTask(ctx context.Context, t *HookTask) (*HookTask, error) {
data, err := t.Payloader.JSONPayload()
if err != nil {
return nil, err
}
t.UUID = gouuid.New().String()
t.PayloadContent = string(data)
if t.Payloader != nil {
data, err := t.Payloader.JSONPayload()
if err != nil {
return nil, err
}
t.PayloadContent = string(data)
}
if t.Delivered == 0 {
t.Delivered = timeutil.TimeStampNanoNow()
}
return t, db.Insert(ctx, t)
}
@ -161,13 +164,11 @@ func ReplayHookTask(ctx context.Context, hookID int64, uuid string) (*HookTask,
}
}
newTask := &HookTask{
UUID: gouuid.New().String(),
return CreateHookTask(ctx, &HookTask{
HookID: task.HookID,
PayloadContent: task.PayloadContent,
EventType: task.EventType,
}
return newTask, db.Insert(ctx, newTask)
})
}
// FindUndeliveredHookTaskIDs will find the next 100 undelivered hook tasks with ID greater than the provided lowerID

View File

@ -12,6 +12,7 @@ import (
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/json"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
webhook_module "code.gitea.io/gitea/modules/webhook"
@ -222,7 +223,6 @@ func TestUpdateHookTask(t *testing.T) {
hook := unittest.AssertExistsAndLoadBean(t, &HookTask{ID: 1})
hook.PayloadContent = "new payload content"
hook.DeliveredString = "new delivered string"
hook.IsDelivered = true
unittest.AssertNotExistsBean(t, hook)
assert.NoError(t, UpdateHookTask(hook))
@ -235,7 +235,7 @@ func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) {
HookID: 3,
Payloader: &api.PushPayload{},
IsDelivered: true,
Delivered: time.Now().UnixNano(),
Delivered: timeutil.TimeStampNanoNow(),
}
unittest.AssertNotExistsBean(t, hookTask)
_, err := CreateHookTask(db.DefaultContext, hookTask)
@ -268,7 +268,7 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) {
HookID: 4,
Payloader: &api.PushPayload{},
IsDelivered: true,
Delivered: time.Now().UnixNano(),
Delivered: timeutil.TimeStampNanoNow(),
}
unittest.AssertNotExistsBean(t, hookTask)
_, err := CreateHookTask(db.DefaultContext, hookTask)
@ -285,7 +285,7 @@ func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) {
HookID: 3,
Payloader: &api.PushPayload{},
IsDelivered: true,
Delivered: time.Now().AddDate(0, 0, -8).UnixNano(),
Delivered: timeutil.TimeStampNano(time.Now().AddDate(0, 0, -8).UnixNano()),
}
unittest.AssertNotExistsBean(t, hookTask)
_, err := CreateHookTask(db.DefaultContext, hookTask)
@ -318,7 +318,7 @@ func TestCleanupHookTaskTable_OlderThan_LeavesTaskEarlierThanAgeToDelete(t *test
HookID: 4,
Payloader: &api.PushPayload{},
IsDelivered: true,
Delivered: time.Now().AddDate(0, 0, -6).UnixNano(),
Delivered: timeutil.TimeStampNano(time.Now().AddDate(0, 0, -6).UnixNano()),
}
unittest.AssertNotExistsBean(t, hookTask)
_, err := CreateHookTask(db.DefaultContext, hookTask)

View File

@ -44,8 +44,7 @@ func (w *wrappedLevelLogger) Log(skip int, level log.Level, format string, v ...
}
func initDBDisableConsole(ctx context.Context, disableConsole bool) error {
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
setting.LoadDBSetting()
setting.InitSQLLog(disableConsole)
if err := db.InitEngine(ctx); err != nil {

View File

@ -66,8 +66,7 @@ func checkConfigurationFiles(ctx context.Context, logger log.Logger, autofix boo
return err
}
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
configurationFiles := []configurationFile{
{"Configuration File Path", setting.CustomConf, false, true, false},

View File

@ -28,8 +28,9 @@ var localMetas = map[string]string{
}
func TestMain(m *testing.M) {
setting.InitProviderAllowEmpty()
setting.LoadCommonSettings()
setting.Init(&setting.Options{
AllowEmpty: true,
})
if err := git.InitSimple(context.Background()); err != nil {
log.Fatal("git init failed, err: %v", err)
}

View File

@ -33,8 +33,9 @@ var localMetas = map[string]string{
}
func TestMain(m *testing.M) {
setting.InitProviderAllowEmpty()
setting.LoadCommonSettings()
setting.Init(&setting.Options{
AllowEmpty: true,
})
if err := git.InitSimple(context.Background()); err != nil {
log.Fatal("git init failed, err: %v", err)
}

View File

@ -4,9 +4,9 @@
package queue
import (
"os"
"strconv"
"sync"
"sync/atomic"
"testing"
"time"
@ -16,10 +16,7 @@ import (
)
func TestPersistableChannelUniqueQueue(t *testing.T) {
if os.Getenv("CI") != "" {
t.Skip("Skipping because test is flaky on CI")
}
// Create a temporary directory for the queue
tmpDir := t.TempDir()
_ = log.NewLogger(1000, "console", "console", `{"level":"warn","stacktracelevel":"NONE","stderr":true}`)
@ -100,7 +97,7 @@ func TestPersistableChannelUniqueQueue(t *testing.T) {
executedInitial := map[string][]string{}
hasInitial := map[string][]string{}
fillQueue := func(name string, done chan struct{}) {
fillQueue := func(name string, done chan int64) {
t.Run("Initial Filling: "+name, func(t *testing.T) {
lock := sync.Mutex{}
@ -157,33 +154,39 @@ func TestPersistableChannelUniqueQueue(t *testing.T) {
assert.Equal(t, 101, len(executedInitial[name])+len(hasInitial[name]))
mapLock.Unlock()
})
mapLock.Lock()
count := int64(len(hasInitial[name]))
mapLock.Unlock()
done <- count
close(done)
}
doneA := make(chan struct{})
doneB := make(chan struct{})
hasQueueAChan := make(chan int64)
hasQueueBChan := make(chan int64)
go fillQueue("QueueA", doneA)
go fillQueue("QueueB", doneB)
go fillQueue("QueueA", hasQueueAChan)
go fillQueue("QueueB", hasQueueBChan)
<-doneA
<-doneB
hasA := <-hasQueueAChan
hasB := <-hasQueueBChan
executedEmpty := map[string][]string{}
hasEmpty := map[string][]string{}
emptyQueue := func(name string, done chan struct{}) {
emptyQueue := func(name string, numInQueue int64, done chan struct{}) {
t.Run("Empty Queue: "+name, func(t *testing.T) {
lock := sync.Mutex{}
stop := make(chan struct{})
// collect the tasks that have been executed
atomicCount := int64(0)
handle := func(data ...Data) []Data {
lock.Lock()
for _, datum := range data {
mapLock.Lock()
executedEmpty[name] = append(executedEmpty[name], datum.(string))
mapLock.Unlock()
if datum.(string) == "final" {
count := atomic.AddInt64(&atomicCount, 1)
if count >= numInQueue {
close(stop)
}
}
@ -217,11 +220,11 @@ func TestPersistableChannelUniqueQueue(t *testing.T) {
close(done)
}
doneA = make(chan struct{})
doneB = make(chan struct{})
doneA := make(chan struct{})
doneB := make(chan struct{})
go emptyQueue("QueueA", doneA)
go emptyQueue("QueueB", doneB)
go emptyQueue("QueueA", hasA, doneA)
go emptyQueue("QueueB", hasB, doneB)
<-doneA
<-doneB
@ -237,20 +240,20 @@ func TestPersistableChannelUniqueQueue(t *testing.T) {
hasEmpty = map[string][]string{}
mapLock.Unlock()
doneA = make(chan struct{})
doneB = make(chan struct{})
hasQueueAChan = make(chan int64)
hasQueueBChan = make(chan int64)
go fillQueue("QueueA", doneA)
go fillQueue("QueueB", doneB)
go fillQueue("QueueA", hasQueueAChan)
go fillQueue("QueueB", hasQueueBChan)
<-doneA
<-doneB
hasA = <-hasQueueAChan
hasB = <-hasQueueBChan
doneA = make(chan struct{})
doneB = make(chan struct{})
go emptyQueue("QueueA", doneA)
go emptyQueue("QueueB", doneB)
go emptyQueue("QueueA", hasA, doneA)
go emptyQueue("QueueB", hasB, doneB)
<-doneA
<-doneB

View File

@ -35,10 +35,9 @@ type ConfigProvider interface {
}
type iniFileConfigProvider struct {
opts *Options
*ini.File
filepath string // the ini file path
newFile bool // whether the file has not existed previously
allowEmpty bool // whether not finding configuration files is allowed (only true for the tests)
newFile bool // whether the file has not existed previously
}
// NewEmptyConfigProvider create a new empty config provider
@ -66,41 +65,47 @@ func newConfigProviderFromData(configContent string) (ConfigProvider, error) {
}, nil
}
type Options struct {
CustomConf string // the ini file path
AllowEmpty bool // whether not finding configuration files is allowed (only true for the tests)
ExtraConfig string
DisableLoadCommonSettings bool
}
// newConfigProviderFromFile load configuration from file.
// NOTE: do not print any log except error.
func newConfigProviderFromFile(customConf string, allowEmpty bool, extraConfig string) (*iniFileConfigProvider, error) {
func newConfigProviderFromFile(opts *Options) (*iniFileConfigProvider, error) {
cfg := ini.Empty()
newFile := true
if customConf != "" {
isFile, err := util.IsFile(customConf)
if opts.CustomConf != "" {
isFile, err := util.IsFile(opts.CustomConf)
if err != nil {
return nil, fmt.Errorf("unable to check if %s is a file. Error: %v", customConf, err)
return nil, fmt.Errorf("unable to check if %s is a file. Error: %v", opts.CustomConf, err)
}
if isFile {
if err := cfg.Append(customConf); err != nil {
return nil, fmt.Errorf("failed to load custom conf '%s': %v", customConf, err)
if err := cfg.Append(opts.CustomConf); err != nil {
return nil, fmt.Errorf("failed to load custom conf '%s': %v", opts.CustomConf, err)
}
newFile = false
}
}
if newFile && !allowEmpty {
if newFile && !opts.AllowEmpty {
return nil, fmt.Errorf("unable to find configuration file: %q, please ensure you are running in the correct environment or set the correct configuration file with -c", CustomConf)
}
if extraConfig != "" {
if err := cfg.Append([]byte(extraConfig)); err != nil {
if opts.ExtraConfig != "" {
if err := cfg.Append([]byte(opts.ExtraConfig)); err != nil {
return nil, fmt.Errorf("unable to append more config: %v", err)
}
}
cfg.NameMapper = ini.SnackCase
return &iniFileConfigProvider{
File: cfg,
filepath: customConf,
newFile: newFile,
allowEmpty: allowEmpty,
opts: opts,
File: cfg,
newFile: newFile,
}, nil
}
@ -123,8 +128,8 @@ func (p *iniFileConfigProvider) DeleteSection(name string) error {
// Save save the content into file
func (p *iniFileConfigProvider) Save() error {
if p.filepath == "" {
if !p.allowEmpty {
if p.opts.CustomConf == "" {
if !p.opts.AllowEmpty {
return fmt.Errorf("custom config path must not be empty")
}
return nil
@ -135,8 +140,8 @@ func (p *iniFileConfigProvider) Save() error {
return fmt.Errorf("failed to create '%s': %v", CustomConf, err)
}
}
if err := p.SaveTo(p.filepath); err != nil {
return fmt.Errorf("failed to save '%s': %v", p.filepath, err)
if err := p.SaveTo(p.opts.CustomConf); err != nil {
return fmt.Errorf("failed to save '%s': %v", p.opts.CustomConf, err)
}
// Change permissions to be more restrictive

View File

@ -15,7 +15,6 @@ import (
"strings"
"time"
"code.gitea.io/gitea/modules/auth/password/hash"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/user"
)
@ -203,46 +202,20 @@ func PrepareAppDataPath() error {
return nil
}
// InitProviderFromExistingFile initializes config provider from an existing config file (app.ini)
func InitProviderFromExistingFile() {
func Init(opts *Options) {
if opts.CustomConf == "" {
opts.CustomConf = CustomConf
}
var err error
CfgProvider, err = newConfigProviderFromFile(CustomConf, false, "")
CfgProvider, err = newConfigProviderFromFile(opts)
if err != nil {
log.Fatal("InitProviderFromExistingFile: %v", err)
log.Fatal("Init[%v]: %v", opts, err)
}
}
// InitProviderAllowEmpty initializes config provider from file, it's also fine that if the config file (app.ini) doesn't exist
func InitProviderAllowEmpty() {
var err error
CfgProvider, err = newConfigProviderFromFile(CustomConf, true, "")
if err != nil {
log.Fatal("InitProviderAllowEmpty: %v", err)
if !opts.DisableLoadCommonSettings {
loadCommonSettingsFrom(CfgProvider)
}
}
// InitProviderAndLoadCommonSettingsForTest initializes config provider and load common setttings for tests
func InitProviderAndLoadCommonSettingsForTest(extraConfigs ...string) {
var err error
CfgProvider, err = newConfigProviderFromFile(CustomConf, true, strings.Join(extraConfigs, "\n"))
if err != nil {
log.Fatal("InitProviderAndLoadCommonSettingsForTest: %v", err)
}
loadCommonSettingsFrom(CfgProvider)
if err := PrepareAppDataPath(); err != nil {
log.Fatal("Can not prepare APP_DATA_PATH: %v", err)
}
// register the dummy hash algorithm function used in the test fixtures
_ = hash.Register("dummy", hash.NewDummyHasher)
PasswordHashAlgo, _ = hash.SetDefaultPasswordHashAlgorithm("dummy")
}
// LoadCommonSettings loads common configurations from a configuration provider.
func LoadCommonSettings() {
loadCommonSettingsFrom(CfgProvider)
}
// loadCommonSettingsFrom loads common configurations from a configuration provider.
func loadCommonSettingsFrom(cfg ConfigProvider) {
// WARNNING: don't change the sequence except you know what you are doing.

View File

@ -0,0 +1,28 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package timeutil
import (
"time"
"code.gitea.io/gitea/modules/setting"
)
// TimeStampNano is for nano time in database, do not use it unless there is a real requirement.
type TimeStampNano int64
// TimeStampNanoNow returns now nano int64
func TimeStampNanoNow() TimeStampNano {
return TimeStampNano(time.Now().UnixNano())
}
// AsTime convert timestamp as time.Time in Local locale
func (tsn TimeStampNano) AsTime() (tm time.Time) {
return tsn.AsTimeInLocation(setting.DefaultUILocation)
}
// AsTimeInLocation convert timestamp as time.Time in Local locale
func (tsn TimeStampNano) AsTimeInLocation(loc *time.Location) time.Time {
return time.Unix(0, int64(tsn)).In(loc)
}

View File

@ -1414,8 +1414,8 @@ issues.context.edit = Edit
issues.context.delete = Delete
issues.no_content = There is no content yet.
issues.close = Close Issue
issues.pull_merged_at = `merged commit <a class="ui sha" href="%[1]s"><code>%[2]s</code></a> into <b>%[3]s</b> %[4]s`
issues.manually_pull_merged_at = `merged commit <a class="ui sha" href="%[1]s"><code>%[2]s</code></a> into <b>%[3]s</b> manually %[4]s`
issues.comment_pull_merged_at = merged commit %[1]s into %[2]s %[3]s
issues.comment_manually_pull_merged_at = manually merged commit %[1]s into %[2]s %[3]s
issues.close_comment_issue = Comment and Close
issues.reopen_issue = Reopen
issues.reopen_comment_issue = Comment and Reopen
@ -2559,6 +2559,7 @@ teams.all_repositories_admin_permission_desc = This team grants <strong>Admin</s
teams.invite.title = You've been invited to join team <strong>%s</strong> in organization <strong>%s</strong>.
teams.invite.by = Invited by %s
teams.invite.description = Please click the button below to join the team.
teams.invite.email_mismatch = Your email address does not match this invite.
[admin]
dashboard = Dashboard

View File

@ -119,6 +119,12 @@ func CommonRoutes(ctx gocontext.Context) *web.Route {
r.Get("/owners", cargo.ListOwners)
})
})
r.Get("/config.json", cargo.RepositoryConfig)
r.Get("/1/{package}", cargo.EnumeratePackageVersions)
r.Get("/2/{package}", cargo.EnumeratePackageVersions)
// Use dummy placeholders because these parts are not of interest
r.Get("/3/{_}/{package}", cargo.EnumeratePackageVersions)
r.Get("/{_}/{__}/{package}", cargo.EnumeratePackageVersions)
}, reqPackageAccess(perm.AccessModeRead))
r.Group("/chef", func() {
r.Group("/api/v1", func() {

View File

@ -4,6 +4,7 @@
package cargo
import (
"errors"
"fmt"
"net/http"
"strconv"
@ -45,6 +46,35 @@ func apiError(ctx *context.Context, status int, obj interface{}) {
})
}
// https://rust-lang.github.io/rfcs/2789-sparse-index.html
func RepositoryConfig(ctx *context.Context) {
ctx.JSON(http.StatusOK, cargo_service.BuildConfig(ctx.Package.Owner))
}
func EnumeratePackageVersions(ctx *context.Context) {
p, err := packages_model.GetPackageByName(ctx, ctx.Package.Owner.ID, packages_model.TypeCargo, ctx.Params("package"))
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
} else {
apiError(ctx, http.StatusInternalServerError, err)
}
return
}
b, err := cargo_service.BuildPackageIndex(ctx, p)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
if b == nil {
apiError(ctx, http.StatusNotFound, nil)
return
}
ctx.PlainTextBytes(http.StatusOK, b.Bytes())
}
type SearchResult struct {
Crates []*SearchResultCrate `json:"crates"`
Meta SearchResultMeta `json:"meta"`

View File

@ -13,10 +13,11 @@ import (
)
func TestMain(m *testing.M) {
setting.InitProviderAndLoadCommonSettingsForTest()
setting.LoadQueueSettings()
unittest.MainTest(m, &unittest.TestOptions{
GiteaRootPath: filepath.Join("..", "..", "..", ".."),
SetUp: webhook_service.Init,
SetUp: func() error {
setting.LoadQueueSettings()
return webhook_service.Init()
},
})
}

View File

@ -15,8 +15,9 @@ import (
// PreloadSettings preloads the configuration to check if we need to run install
func PreloadSettings(ctx context.Context) bool {
setting.InitProviderAllowEmpty()
setting.LoadCommonSettings()
setting.Init(&setting.Options{
AllowEmpty: true,
})
if !setting.InstallLock {
log.Info("AppPath: %s", setting.AppPath)
log.Info("AppWorkPath: %s", setting.AppWorkPath)
@ -38,8 +39,7 @@ func PreloadSettings(ctx context.Context) bool {
// reloadSettings reloads the existing settings and starts up the database
func reloadSettings(ctx context.Context) {
setting.InitProviderFromExistingFile()
setting.LoadCommonSettings()
setting.Init(&setting.Options{})
setting.LoadDBSetting()
if setting.InstallLock {
if err := common.InitDBEngine(ctx); err == nil {

View File

@ -552,6 +552,7 @@ func TeamInvite(ctx *context.Context) {
ctx.Data["Organization"] = org
ctx.Data["Team"] = team
ctx.Data["Inviter"] = inviter
ctx.Data["EmailMismatch"] = ctx.Doer.Email != invite.Email
ctx.HTML(http.StatusOK, tplTeamInvite)
}
@ -568,6 +569,13 @@ func TeamInvitePost(ctx *context.Context) {
return
}
// check that the Doer is the invitee
if ctx.Doer.Email != invite.Email {
log.Info("invite %d does not apply to the current user %d", invite.ID, ctx.Doer.ID)
ctx.NotFound("ErrTeamInviteNotFound", err)
return
}
if err := models.AddTeamMember(team, ctx.Doer.ID); err != nil {
ctx.ServerError("AddTeamMember", err)
return

View File

@ -80,19 +80,22 @@ func TestChangePassword(t *testing.T) {
PasswordComplexity: pcLU,
},
} {
unittest.PrepareTestEnv(t)
ctx := test.MockContext(t, "user/settings/security")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
t.Run(req.OldPassword+"__"+req.NewPassword, func(t *testing.T) {
unittest.PrepareTestEnv(t)
setting.PasswordComplexity = req.PasswordComplexity
ctx := test.MockContext(t, "user/settings/security")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
web.SetForm(ctx, &forms.ChangePasswordForm{
OldPassword: req.OldPassword,
Password: req.NewPassword,
Retype: req.Retype,
web.SetForm(ctx, &forms.ChangePasswordForm{
OldPassword: req.OldPassword,
Password: req.NewPassword,
Retype: req.Retype,
})
AccountPost(ctx)
assert.Contains(t, ctx.Flash.ErrorMsg, req.Message)
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
})
AccountPost(ctx)
assert.Contains(t, ctx.Flash.ErrorMsg, req.Message)
assert.EqualValues(t, http.StatusSeeOther, ctx.Resp.Status())
}
}

View File

@ -137,21 +137,21 @@ type IndexVersionEntry struct {
Links string `json:"links,omitempty"`
}
func addOrUpdatePackageIndex(ctx context.Context, t *files_service.TemporaryUploadRepository, p *packages_model.Package) error {
func BuildPackageIndex(ctx context.Context, p *packages_model.Package) (*bytes.Buffer, error) {
pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
PackageID: p.ID,
Sort: packages_model.SortVersionAsc,
})
if err != nil {
return fmt.Errorf("SearchVersions[%s]: %w", p.Name, err)
return nil, fmt.Errorf("SearchVersions[%s]: %w", p.Name, err)
}
if len(pvs) == 0 {
return nil
return nil, nil
}
pds, err := packages_model.GetPackageDescriptors(ctx, pvs)
if err != nil {
return fmt.Errorf("GetPackageDescriptors[%s]: %w", p.Name, err)
return nil, fmt.Errorf("GetPackageDescriptors[%s]: %w", p.Name, err)
}
var b bytes.Buffer
@ -179,14 +179,26 @@ func addOrUpdatePackageIndex(ctx context.Context, t *files_service.TemporaryUplo
Links: metadata.Links,
})
if err != nil {
return err
return nil, err
}
b.Write(entry)
b.WriteString("\n")
}
return writeObjectToIndex(t, BuildPackagePath(pds[0].Package.LowerName), &b)
return &b, nil
}
func addOrUpdatePackageIndex(ctx context.Context, t *files_service.TemporaryUploadRepository, p *packages_model.Package) error {
b, err := BuildPackageIndex(ctx, p)
if err != nil {
return err
}
if b == nil {
return nil
}
return writeObjectToIndex(t, BuildPackagePath(p.LowerName), b)
}
func getOrCreateIndexRepository(ctx context.Context, doer, owner *user_model.User) (*repo_model.Repository, error) {
@ -212,6 +224,13 @@ type Config struct {
APIURL string `json:"api"`
}
func BuildConfig(owner *user_model.User) *Config {
return &Config{
DownloadURL: setting.AppURL + "api/packages/" + owner.Name + "/cargo/api/v1/crates",
APIURL: setting.AppURL + "api/packages/" + owner.Name + "/cargo",
}
}
func createOrUpdateConfigFile(ctx context.Context, repo *repo_model.Repository, doer, owner *user_model.User) error {
return alterRepositoryContent(
ctx,
@ -220,10 +239,7 @@ func createOrUpdateConfigFile(ctx context.Context, repo *repo_model.Repository,
"Initialize Cargo Config",
func(t *files_service.TemporaryUploadRepository) error {
var b bytes.Buffer
err := json.NewEncoder(&b).Encode(Config{
DownloadURL: setting.AppURL + "api/packages/" + owner.Name + "/cargo/api/v1/crates",
APIURL: setting.AppURL + "api/packages/" + owner.Name + "/cargo",
})
err := json.NewEncoder(&b).Encode(BuildConfig(owner))
if err != nil {
return err
}

View File

@ -25,6 +25,7 @@ import (
"code.gitea.io/gitea/modules/proxy"
"code.gitea.io/gitea/modules/queue"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
webhook_module "code.gitea.io/gitea/modules/webhook"
"github.com/gobwas/glob"
@ -175,7 +176,7 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
// All code from this point will update the hook task
defer func() {
t.Delivered = time.Now().UnixNano()
t.Delivered = timeutil.TimeStampNanoNow()
if t.IsSucceed {
log.Trace("Hook delivered: %s", t.UUID)
} else if !w.IsActive {

View File

@ -15,13 +15,13 @@ import (
)
func TestMain(m *testing.M) {
setting.InitProviderAndLoadCommonSettingsForTest()
setting.LoadQueueSettings()
// for tests, allow only loopback IPs
setting.Webhook.AllowedHostList = hostmatcher.MatchBuiltinLoopback
unittest.MainTest(m, &unittest.TestOptions{
GiteaRootPath: filepath.Join("..", ".."),
SetUp: Init,
SetUp: func() error {
setting.LoadQueueSettings()
return Init()
},
})
}

View File

@ -1,20 +1,20 @@
{{if .Flash.ErrorMsg}}
<div class="ui negative message flash-error">
<div class="ui negative message flash-message flash-error">
<p>{{.Flash.ErrorMsg | Str2html}}</p>
</div>
{{end}}
{{if .Flash.SuccessMsg}}
<div class="ui positive message flash-success">
<div class="ui positive message flash-message flash-success">
<p>{{.Flash.SuccessMsg | Str2html}}</p>
</div>
{{end}}
{{if .Flash.InfoMsg}}
<div class="ui info message flash-info">
<div class="ui info message flash-message flash-info">
<p>{{.Flash.InfoMsg | Str2html}}</p>
</div>
{{end}}
{{if .Flash.WarningMsg}}
<div class="ui warning message flash-warning">
<div class="ui warning message flash-message flash-warning">
<p>{{.Flash.WarningMsg | Str2html}}</p>
</div>
{{end}}

View File

@ -7,7 +7,7 @@
<div class="list">
{{range .Members}}
<div class="item ui grid">
<div class="ui four wide column" style="display: flex;">
<div class="ui four wide column gt-df">
<a href="{{.HomeLink}}">{{avatar $.Context . 48}}</a>
<div>
<div class="meta"><a href="{{.HomeLink}}">{{.Name}}</a></div>

View File

@ -6,17 +6,23 @@
<div class="image">
{{avatar $.Context .Organization 140}}
</div>
<div class="content">
<div class="header">{{.locale.Tr "org.teams.invite.title" .Team.Name .Organization.Name | Str2html}}</div>
<div class="meta">{{.locale.Tr "org.teams.invite.by" .Inviter.Name}}</div>
<div class="description">{{.locale.Tr "org.teams.invite.description"}}</div>
</div>
<div class="extra content">
<form class="ui form" action="" method="post">
{{.CsrfTokenHtml}}
<button class="fluid ui green button">{{.locale.Tr "org.teams.join"}}</button>
</form>
</div>
{{if .EmailMismatch}}
<div class="content">
<div class="header">{{.locale.Tr "org.teams.invite.email_mismatch"}}</div>
</div>
{{else}}
<div class="content">
<div class="header">{{.locale.Tr "org.teams.invite.title" .Team.Name .Organization.Name | Str2html}}</div>
<div class="meta">{{.locale.Tr "org.teams.invite.by" .Inviter.Name}}</div>
<div class="description">{{.locale.Tr "org.teams.invite.description"}}</div>
</div>
<div class="extra content">
<form class="ui form" action="" method="post">
{{.CsrfTokenHtml}}
<button class="fluid ui green button">{{.locale.Tr "org.teams.join"}}</button>
</form>
</div>
{{end}}
</div>
</div>
</div>

View File

@ -69,7 +69,7 @@
{{if .PackageDescriptor.Metadata.Labels}}
<h4 class="ui top attached header">{{.locale.Tr "packages.container.labels"}}</h4>
<div class="ui attached segment">
<table class="ui very basic compact table container-labels">
<table class="ui very basic compact table">
<thead>
<tr>
<th>{{.locale.Tr "packages.container.labels.key"}}</th>
@ -79,8 +79,8 @@
<tbody>
{{range $key, $value := .PackageDescriptor.Metadata.Labels}}
<tr>
<td>{{$key}}</td>
<td>{{$value}}</td>
<td class="top aligned">{{$key}}</td>
<td class="gt-word-break">{{$value}}</td>
</tr>
{{end}}
</tbody>

View File

@ -51,7 +51,7 @@
{{.locale.Tr "packages.settings.delete"}}
</div>
<div class="content">
<div class="ui warning message text left gt-word-break">
<div class="ui warning message gt-word-break">
{{.locale.Tr "packages.settings.delete.notice" .PackageDescriptor.Package.Name .PackageDescriptor.Version.Version}}
</div>
<form class="ui form" action="{{.Link}}" method="post">

View File

@ -10,7 +10,7 @@
{{end}}
{{template "base/alert" .}}
<div class="small-pill-buttons ui compact tiny menu">
<div class="small-menu-items ui compact tiny menu">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{$.Link}}?state=open">
{{svg "octicon-project-symlink" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}

View File

@ -1,4 +1,4 @@
<div class="small-pill-buttons ui compact tiny menu">
<div class="small-menu-items ui compact tiny menu">
<a class="{{if not .IsShowClosed}}active {{end}}item" href="{{$.Link}}?workflow={{.CurWorkflow}}&state=open">
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
{{.locale.Tr "actions.runs.open_tab" $.NumOpenActionRuns}}

View File

@ -1,3 +1,8 @@
{{/* Attributes:
* root
* ContainerClasses
* (TODO: search "branch_dropdown" in the template direcotry)
*/}}
{{$defaultBranch := $.root.BranchName}}
{{if and .root.IsViewTag (not .noTag)}}
{{$defaultBranch = .root.TagName}}
@ -62,10 +67,10 @@
window.config.pageData.branchDropdownDataList.push(data);
</script>
<div class="fitted item js-branch-tag-selector">
<div class="js-branch-tag-selector {{if .ContainerClasses}}{{.ContainerClasses}}{{end}}">
{{/* show dummy elements before Vue componment is mounted, this code must match the code in BranchTagSelector.vue */}}
<div class="ui floating filter dropdown custom">
<button class="branch-dropdown-button gt-ellipsis ui basic small compact button gt-df">
<button class="branch-dropdown-button gt-ellipsis ui basic small compact button gt-df gt-m-0">
<span class="text gt-df gt-ac gt-mr-2">
{{if .release}}
{{.root.locale.Tr "repo.release.compare"}}

View File

@ -5,7 +5,7 @@
{{template "repo/sub_menu" .}}
<div class="repo-button-row gt-df gt-ac gt-sb gt-fw gt-mb-4 gt-mt-3">
<div class="gt-df gt-ac">
{{template "repo/branch_dropdown" dict "root" .}}
{{template "repo/branch_dropdown" dict "root" . "ContainerClasses" "gt-mr-2"}}
<a href="{{.RepoLink}}/graph" class="ui basic small compact button">
<span class="text">
{{svg "octicon-git-branch"}}

View File

@ -63,7 +63,7 @@
{{template "repo/sub_menu" .}}
<div class="repo-button-row gt-df gt-ac gt-sb gt-fw">
<div class="gt-df gt-ac gt-fw gt-gap-y-3">
{{template "repo/branch_dropdown" dict "root" .}}
{{template "repo/branch_dropdown" dict "root" . "ContainerClasses" "gt-mr-2"}}
{{$n := len .TreeNames}}
{{$l := Eval $n "-" 1}}
<!-- If home page, show new pr. If not, show breadcrumb -->

View File

@ -2,7 +2,7 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository labels">
{{template "repo/header" .}}
<div class="ui container">
<div class="navbar">
<div class="navbar gt-mb-4">
{{template "repo/issue/navbar" .}}
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}}
<div class="ui right">
@ -10,7 +10,6 @@
</div>
{{end}}
</div>
<div class="ui divider"></div>
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}}
{{template "repo/issue/labels/label_new" .}}
{{end}}

View File

@ -17,9 +17,6 @@
{{end}}
{{end}}
</div>
<div class="ui divider"></div>
<div id="issue-filters" class="issue-list-toolbar">
<div class="issue-list-toolbar-left">
{{if $.CanWriteIssuesOrPulls}}

View File

@ -2,7 +2,7 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository milestones">
{{template "repo/header" .}}
<div class="ui container">
<div class="navbar">
<div class="navbar gt-mb-4">
{{template "repo/issue/navbar" .}}
{{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}}
<div class="ui right">
@ -10,11 +10,10 @@
</div>
{{end}}
</div>
<div class="ui divider"></div>
{{template "base/alert" .}}
<div class="list-header">
<div class="small-pill-buttons ui compact tiny menu">
<div class="small-menu-items ui compact tiny menu">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/milestones?state=open&q={{$.Keyword}}">
{{svg "octicon-milestone" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}

View File

@ -1,4 +1,4 @@
<h2 class="ui compact small menu header small-pill-buttons">
<h2 class="ui compact small menu header small-menu-items">
<a class="{{if .PageIsLabels}}active {{end}}item" href="{{.RepoLink}}/labels">{{.locale.Tr "repo.labels"}}</a>
<a class="{{if .PageIsMilestones}}active {{end}}item" href="{{.RepoLink}}/milestones">{{.locale.Tr "repo.milestones"}}</a>
</h2>

View File

@ -2,10 +2,6 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository new issue">
{{template "repo/header" .}}
<div class="ui container">
<div class="navbar">
{{template "repo/issue/navbar" .}}
</div>
<div class="ui divider"></div>
{{if .Flash.WarningMsg}}
{{/*
There's already an importing of alert.tmpl in new_form.tmpl,

View File

@ -1,4 +1,4 @@
<div class="small-pill-buttons ui compact tiny menu">
<div class="small-menu-items ui compact tiny menu">
<a class="{{if not .IsShowClosed}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&sort={{$.SortType}}&state=open&labels={{.SelectLabels}}&milestone={{.MilestoneID}}&project={{.ProjectID}}&assignee={{.AssigneeID}}&poster={{.PosterID}}">
{{if .PageIsPullList}}
{{svg "octicon-git-pull-request" 16 "gt-mr-3"}}

View File

@ -2,32 +2,11 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository view issue pull">
{{template "repo/header" .}}
<div class="ui container">
<div class="ui two column grid">
<div class="column">
{{template "repo/issue/navbar" .}}
</div>
{{if and (not .Repository.IsArchived) (not .Issue.IsPull)}}
<div class="column right aligned">
{{if .PageIsIssueList}}
<a class="ui green button" href="{{.RepoLink}}/issues/new{{if .NewIssueChooseTemplate}}/choose{{end}}">{{.locale.Tr "repo.issues.new"}}</a>
{{else}}
<a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | PathEscapeSegments}}...{{.PullRequestCtx.HeadInfoSubURL}}">{{.locale.Tr "repo.pulls.new"}}</a>
{{end}}
</div>
{{end}}
</div>
<div class="ui divider"></div>
{{template "repo/issue/view_title" .}}
{{if .Issue.IsPull}}
{{template "repo/issue/view_title" .}}
{{template "repo/pulls/tab_menu" .}}
<div class="ui bottom attached tab pull active" data-tab="request-{{.ID}}">
{{template "repo/issue/view_content" .}}
</div>
{{else}}
<div>
{{template "repo/issue/view_content" .}}
</div>
{{end}}
{{template "repo/issue/view_content" .}}
</div>
</div>
{{template "base/footer" .}}

View File

@ -1,13 +1,4 @@
<div class="ui stackable grid">
{{if .Flash}}
<div class="sixteen wide column">
{{template "base/alert" .}}
</div>
{{end}}
{{if not .Issue.IsPull}}
{{template "repo/issue/view_title" .}}
{{end}}
<!-- I know, there is probably a better way to do this (moved from sidebar.tmpl, original author: 6543 @ 2021-02-28) -->
<!-- Agree, there should be a better way, eg: introduce window.config.pageData (original author: wxiaoguang @ 2021-09-05) -->
<input type="hidden" id="repolink" value="{{$.RepoRelPath}}">

View File

@ -125,9 +125,9 @@
{{template "shared/user/authorlink" .Poster}}
{{$link := printf "%s/commit/%s" $.Repository.Link ($.Issue.PullRequest.MergedCommitID|PathEscape)}}
{{if eq $.Issue.PullRequest.Status 3}}
{{$.locale.Tr "repo.issues.manually_pull_merged_at" ($link|Escape) (ShortSha $.Issue.PullRequest.MergedCommitID) ($.BaseTarget|Escape) $createdStr | Safe}}
{{$.locale.Tr "repo.issues.comment_manually_pull_merged_at" (printf "<a class='ui sha' href='%[1]s'><b>%[2]s</b></a>" ($link|Escape) (ShortSha $.Issue.PullRequest.MergedCommitID)) (printf "<b>%[1]s</b>" ($.BaseTarget|Escape)) $createdStr | Safe}}
{{else}}
{{$.locale.Tr "repo.issues.pull_merged_at" ($link|Escape) (ShortSha $.Issue.PullRequest.MergedCommitID) ($.BaseTarget|Escape) $createdStr | Safe}}
{{$.locale.Tr "repo.issues.comment_pull_merged_at" (printf "<a class='ui sha' href='%[1]s'><b>%[2]s</b></a>" ($link|Escape) (ShortSha $.Issue.PullRequest.MergedCommitID)) (printf "<b>%[1]s</b>" ($.BaseTarget|Escape)) $createdStr | Safe}}
{{end}}
</span>
</div>

View File

@ -47,7 +47,7 @@
{{$.locale.Tr "repo.issues.dismiss_review"}}
</div>
<div class="content">
<div class="ui warning message text left">
<div class="ui warning message">
{{$.locale.Tr "repo.issues.dismiss_review_warning"}}
</div>
<form class="ui form dismiss-review-form" id="dismiss-review-{{.Review.ID}}" action="{{$.RepoLink}}/issues/dismiss_review" method="post">
@ -108,6 +108,9 @@
</div>
</div>
{{end}}
{{if and .Issue.PullRequest.HasMerged (not .IsPullBranchDeletable)}}
{{/* Then the merge box will not be displayed because this page already contains enough information */}}
{{else}}
<div class="timeline-item comment merge box">
<a class="timeline-avatar text {{if .Issue.PullRequest.HasMerged}}purple
{{- else if .Issue.IsClosed}}grey
@ -131,19 +134,21 @@
{{$showGeneralMergeForm := false}}
<div class="ui attached merge-section segment {{if not $.LatestCommitStatus}}no-header{{end}}">
{{if .Issue.PullRequest.HasMerged}}
<div class="item item-section text gt-f1">
<div class="item-section-left">
<h3 class="gt-mb-3">{{$.locale.Tr "repo.pulls.merged_success"}}</h3>
<div class="merge-section-info">
{{$.locale.Tr "repo.pulls.merged_info_text" (printf "<code>%s</code>" (.HeadTarget | Escape)) | Str2html}}
{{if .IsPullBranchDeletable}}
<div class="item item-section text gt-f1">
<div class="item-section-left">
<h3 class="gt-mb-3">
{{$.locale.Tr "repo.pulls.merged_success"}}
</h3>
<div class="merge-section-info">
{{$.locale.Tr "repo.pulls.merged_info_text" (printf "<code>%s</code>" (.HeadTarget | Escape)) | Str2html}}
</div>
</div>
</div>
{{if .IsPullBranchDeletable}}
<div class="item-section-right">
<button class="delete-button ui button" data-url="{{.DeleteBranchLink}}">{{$.locale.Tr "repo.branch.delete_html"}}</button>
</div>
{{end}}
</div>
</div>
{{end}}
{{else if .Issue.IsClosed}}
<div class="item item-section text gt-f1">
<div class="item-section-left">
@ -485,3 +490,4 @@
</div>
</div>
</div>
{{end}}

View File

@ -560,7 +560,7 @@
{{end}}
</div>
<div class="content">
<div class="ui warning message text left">
<div class="ui warning message">
{{if .Issue.IsLocked}}
{{.locale.Tr "repo.issues.unlock.notice_1"}}<br>
{{.locale.Tr "repo.issues.unlock.notice_2"}}<br>

View File

@ -1,107 +1,119 @@
<div class="sixteen wide column title">
{{if .Flash}}
<div class="sixteen wide column gt-mb-3">
{{template "base/alert" .}}
</div>
{{end}}
<div class="issue-title-header">
<div class="issue-title" id="issue-title-wrapper">
{{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .Repository.IsArchived)}}
<button id="edit-title" class="ui basic button secondary edit-button not-in-edit">{{.locale.Tr "repo.issues.edit"}}</button>
{{end}}
<h1>
<span id="issue-title">{{RenderIssueTitle $.Context .Issue.Title $.RepoLink $.Repository.ComposeMetas | RenderCodeBlock}}</span>
<span class="index">#{{.Issue.Index}}</span>
<div id="edit-title-input" class="ui input gt-ml-4 gt-hidden">
<h1 class="gt-word-break">
<span id="issue-title">{{RenderIssueTitle $.Context .Issue.Title $.RepoLink $.Repository.ComposeMetas | RenderCodeBlock}} <span class="index">#{{.Issue.Index}}</span>
</span>
<div id="edit-title-input" class="ui input gt-f1 gt-hidden">
<input value="{{.Issue.Title}}" maxlength="255" autocomplete="off">
</div>
</h1>
<div class="issue-title-buttons">
{{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .Repository.IsArchived)}}
<button id="edit-title" class="ui small basic button secondary edit-button not-in-edit{{if .Issue.IsPull}} gt-mr-0{{end}}">{{.locale.Tr "repo.issues.edit"}}</button>
{{end}}
{{if not .Issue.IsPull}}
<a role="button" class="ui small green button new-issue-button gt-mr-0" href="{{.RepoLink}}/issues/new{{if .NewIssueChooseTemplate}}/choose{{end}}">{{.locale.Tr "repo.issues.new"}}</a>
{{end}}
</div>
{{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .Repository.IsArchived)}}
<div class="edit-buttons">
<button id="cancel-edit-title" class="ui basic button secondary in-edit gt-hidden">{{.locale.Tr "repo.issues.cancel"}}</button>
<button id="save-edit-title" class="ui primary button in-edit gt-hidden" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/title" {{if .Issue.IsPull}}data-target-update-url="{{$.RepoLink}}/pull/{{.Issue.Index}}/target_branch"{{end}}>{{.locale.Tr "repo.issues.save"}}</button>
<button id="cancel-edit-title" class="ui small basic button secondary in-edit gt-hidden">{{.locale.Tr "repo.issues.cancel"}}</button>
<button id="save-edit-title" class="ui small primary button in-edit gt-hidden gt-mr-0" data-update-url="{{$.RepoLink}}/issues/{{.Issue.Index}}/title" {{if .Issue.IsPull}}data-target-update-url="{{$.RepoLink}}/pull/{{.Issue.Index}}/target_branch"{{end}}>{{.locale.Tr "repo.issues.save"}}</button>
</div>
{{end}}
</div>
{{if .HasMerged}}
<div class="ui purple large label">{{svg "octicon-git-merge" 16}} {{if eq .Issue.PullRequest.Status 3}}{{.locale.Tr "repo.pulls.manually_merged"}}{{else}}{{.locale.Tr "repo.pulls.merged"}}{{end}}</div>
{{else if .Issue.IsClosed}}
<div class="ui red large label">{{if .Issue.IsPull}}{{svg "octicon-git-pull-request"}}{{else}}{{svg "octicon-issue-closed"}}{{end}} {{.locale.Tr "repo.issues.closed_title"}}</div>
{{else if .Issue.IsPull}}
{{if .IsPullWorkInProgress}}
<div class="ui grey large label">{{svg "octicon-git-pull-request-draft"}} {{.locale.Tr "repo.issues.draft_title"}}</div>
{{else}}
<div class="ui green large label">{{svg "octicon-git-pull-request"}} {{.locale.Tr "repo.issues.open_title"}}</div>
{{end}}
{{else}}
<div class="ui green large label">{{svg "octicon-issue-opened"}} {{.locale.Tr "repo.issues.open_title"}}</div>
{{end}}
{{if .Issue.IsPull}}
{{$headHref := .HeadTarget|Escape}}
{{if .HeadBranchLink}}
{{$headHref = printf "<a href=\"%s\">%s</a>" (.HeadBranchLink | Escape) $headHref}}
{{end}}
{{$headHref = printf "%s <a data-tooltip-content=\"%s\" data-clipboard-text=\"%s\">%s</a>" $headHref (.locale.Tr "copy_branch") (.HeadTarget | Escape) (svg "octicon-copy" 14)}}
{{$baseHref := .BaseTarget|Escape}}
{{if .BaseBranchLink}}
{{$baseHref = printf "<a href=\"%s\">%s</a>" (.BaseBranchLink | Escape) $baseHref}}
{{end}}
{{if .Issue.PullRequest.HasMerged}}
{{$mergedStr:= TimeSinceUnix .Issue.PullRequest.MergedUnix $.locale}}
{{if .Issue.OriginalAuthor}}
{{.Issue.OriginalAuthor}}
<span class="pull-desc">{{$.locale.Tr "repo.pulls.merged_title_desc" .NumCommits $headHref $baseHref $mergedStr | Safe}}</span>
<div class="issue-title-meta">
{{if .HasMerged}}
<div class="ui purple label issue-state-label">{{svg "octicon-git-merge" 16 "gt-mr-2"}} {{if eq .Issue.PullRequest.Status 3}}{{.locale.Tr "repo.pulls.manually_merged"}}{{else}}{{.locale.Tr "repo.pulls.merged"}}{{end}}</div>
{{else if .Issue.IsClosed}}
<div class="ui red label issue-state-label">{{if .Issue.IsPull}}{{svg "octicon-git-pull-request"}}{{else}}{{svg "octicon-issue-closed"}}{{end}} {{.locale.Tr "repo.issues.closed_title"}}</div>
{{else if .Issue.IsPull}}
{{if .IsPullWorkInProgress}}
<div class="ui grey label issue-state-label">{{svg "octicon-git-pull-request-draft"}} {{.locale.Tr "repo.issues.draft_title"}}</div>
{{else}}
<a {{if gt .Issue.PullRequest.Merger.ID 0}}href="{{.Issue.PullRequest.Merger.HomeLink}}"{{end}}>{{.Issue.PullRequest.Merger.GetDisplayName}}</a>
<span class="pull-desc">{{$.locale.Tr "repo.pulls.merged_title_desc" .NumCommits $headHref $baseHref $mergedStr | Safe}}</span>
<div class="ui green label issue-state-label">{{svg "octicon-git-pull-request"}} {{.locale.Tr "repo.issues.open_title"}}</div>
{{end}}
{{else}}
{{if .Issue.OriginalAuthor}}
<span id="pull-desc" class="pull-desc">{{.Issue.OriginalAuthor}} {{$.locale.Tr "repo.pulls.title_desc" .NumCommits $headHref $baseHref | Safe}}</span>
<div class="ui green label issue-state-label">{{svg "octicon-issue-opened"}} {{.locale.Tr "repo.issues.open_title"}}</div>
{{end}}
<div class="gt-ml-3">
{{if .Issue.IsPull}}
{{$headHref := .HeadTarget|Escape}}
{{if .HeadBranchLink}}
{{$headHref = printf "<a href=\"%s\">%s</a>" (.HeadBranchLink | Escape) $headHref}}
{{end}}
{{$headHref = printf "%s <a data-tooltip-content=\"%s\" data-clipboard-text=\"%s\">%s</a>" $headHref (.locale.Tr "copy_branch") (.HeadTarget | Escape) (svg "octicon-copy" 14)}}
{{$baseHref := .BaseTarget|Escape}}
{{if .BaseBranchLink}}
{{$baseHref = printf "<a href=\"%s\">%s</a>" (.BaseBranchLink | Escape) $baseHref}}
{{end}}
{{if .Issue.PullRequest.HasMerged}}
{{$mergedStr:= TimeSinceUnix .Issue.PullRequest.MergedUnix $.locale}}
{{if .Issue.OriginalAuthor}}
{{.Issue.OriginalAuthor}}
<span class="pull-desc">{{$.locale.Tr "repo.pulls.merged_title_desc" .NumCommits $headHref $baseHref $mergedStr | Safe}}</span>
{{else}}
<a {{if gt .Issue.PullRequest.Merger.ID 0}}href="{{.Issue.PullRequest.Merger.HomeLink}}"{{end}}>{{.Issue.PullRequest.Merger.GetDisplayName}}</a>
<span class="pull-desc">{{$.locale.Tr "repo.pulls.merged_title_desc" .NumCommits $headHref $baseHref $mergedStr | Safe}}</span>
{{end}}
{{else}}
{{if .Issue.OriginalAuthor}}
<span id="pull-desc" class="pull-desc">{{.Issue.OriginalAuthor}} {{$.locale.Tr "repo.pulls.title_desc" .NumCommits $headHref $baseHref | Safe}}</span>
{{else}}
<span id="pull-desc" class="pull-desc">
<a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.GetDisplayName}}</a>
{{$.locale.Tr "repo.pulls.title_desc" .NumCommits $headHref $baseHref | Safe}}
</span>
{{end}}
<span id="pull-desc-edit" class="gt-hidden">
<div class="ui floating filter dropdown">
<div class="ui basic small button">
<span class="text">{{.locale.Tr "repo.pulls.compare_compare"}}: {{$.HeadTarget}}</span>
</div>
</div>
{{svg "octicon-arrow-right"}}
<div class="ui floating filter dropdown" data-no-results="{{.locale.Tr "repo.pulls.no_results"}}">
<div class="ui basic small button">
<span class="text" id="pull-target-branch" data-basename="{{$.BaseName}}" data-branch="{{$.BaseBranch}}">{{.locale.Tr "repo.pulls.compare_base"}}: {{$.BaseName}}:{{$.BaseBranch}}</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</div>
<div class="menu">
<div class="ui icon search input">
<i class="icon gt-df gt-ac gt-jc gt-m-0">{{svg "octicon-filter" 16}}</i>
<input name="search" placeholder="{{.locale.Tr "repo.pulls.filter_branch"}}...">
</div>
<div class="scrolling menu" id="branch-select">
{{range .Branches}}
{{$sameBase := ne $.BaseName $.HeadUserName}}
{{$differentBranch := ne . $.HeadBranch}}
{{if or $sameBase $differentBranch}}
<div class="item {{if eq $.BaseBranch .}}selected{{end}}" data-branch="{{.}}">{{$.BaseName}}{{if $.HeadRepo}}/{{$.HeadRepo}}{{end}}:{{.}}</div>
{{end}}
{{end}}
</div>
</div>
</div>
</span>
{{end}}
{{else}}
<span id="pull-desc" class="pull-desc">
<a {{if gt .Issue.Poster.ID 0}}href="{{.Issue.Poster.HomeLink}}"{{end}}>{{.Issue.Poster.GetDisplayName}}</a>
{{$.locale.Tr "repo.pulls.title_desc" .NumCommits $headHref $baseHref | Safe}}
{{$createdStr:= TimeSinceUnix .Issue.CreatedUnix $.locale}}
<span class="time-desc">
{{if .Issue.OriginalAuthor}}
{{$.locale.Tr "repo.issues.opened_by_fake" $createdStr (.Issue.OriginalAuthor|Escape) | Safe}}
{{else if gt .Issue.Poster.ID 0}}
{{$.locale.Tr "repo.issues.opened_by" $createdStr (.Issue.Poster.HomeLink|Escape) (.Issue.Poster.GetDisplayName|Escape) | Safe}}
{{else}}
{{$.locale.Tr "repo.issues.opened_by_fake" $createdStr (.Issue.Poster.GetDisplayName|Escape) | Safe}}
{{end}}
·
{{$.locale.Tr "repo.issues.num_comments" .Issue.NumComments}}
</span>
{{end}}
<span id="pull-desc-edit" class="gt-hidden">
<div class="ui floating filter dropdown">
<div class="ui basic small button">
<span class="text">{{.locale.Tr "repo.pulls.compare_compare"}}: {{$.HeadTarget}}</span>
</div>
</div>
{{svg "octicon-arrow-right"}}
<div class="ui floating filter dropdown" data-no-results="{{.locale.Tr "repo.pulls.no_results"}}">
<div class="ui basic small button">
<span class="text" id="pull-target-branch" data-basename="{{$.BaseName}}" data-branch="{{$.BaseBranch}}">{{.locale.Tr "repo.pulls.compare_base"}}: {{$.BaseName}}:{{$.BaseBranch}}</span>
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</div>
<div class="menu">
<div class="ui icon search input">
<i class="icon gt-df gt-ac gt-jc gt-m-0">{{svg "octicon-filter" 16}}</i>
<input name="search" placeholder="{{.locale.Tr "repo.pulls.filter_branch"}}...">
</div>
<div class="scrolling menu" id="branch-select">
{{range .Branches}}
{{$sameBase := ne $.BaseName $.HeadUserName}}
{{$differentBranch := ne . $.HeadBranch}}
{{if or $sameBase $differentBranch}}
<div class="item {{if eq $.BaseBranch .}}selected{{end}}" data-branch="{{.}}">{{$.BaseName}}{{if $.HeadRepo}}/{{$.HeadRepo}}{{end}}:{{.}}</div>
{{end}}
{{end}}
</div>
</div>
</div>
</span>
{{end}}
{{else}}
{{$createdStr:= TimeSinceUnix .Issue.CreatedUnix $.locale}}
<span class="time-desc">
{{if .Issue.OriginalAuthor}}
{{$.locale.Tr "repo.issues.opened_by_fake" $createdStr (.Issue.OriginalAuthor|Escape) | Safe}}
{{else if gt .Issue.Poster.ID 0}}
{{$.locale.Tr "repo.issues.opened_by" $createdStr (.Issue.Poster.HomeLink|Escape) (.Issue.Poster.GetDisplayName|Escape) | Safe}}
{{else}}
{{$.locale.Tr "repo.issues.opened_by_fake" $createdStr (.Issue.Poster.GetDisplayName|Escape) | Safe}}
{{end}}
·
{{$.locale.Tr "repo.issues.num_comments" .Issue.NumComments}}
</span>
{{end}}
<div class="ui divider"></div>
</div>
</div>
</div>

View File

@ -50,7 +50,7 @@
{{.locale.Tr "repo.settings.delete"}}
</div>
<div class="content">
<div class="ui warning message text left">
<div class="ui warning message">
{{.locale.Tr "repo.settings.delete_notices_1" | Safe}}<br>
{{.locale.Tr "repo.settings.delete_notices_2" .Repository.FullName | Safe}}
{{if .Repository.NumForks}}<br>

View File

@ -2,41 +2,39 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository projects milestones">
{{template "repo/header" .}}
<div class="ui container">
<div class="navbar">
{{template "repo/issue/navbar" .}}
{{if and .CanWriteProjects (not .Repository.IsArchived)}}
<div class="ui right">
<a class="ui small green button" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a>
</div>
{{end}}
</div>
<div class="ui divider"></div>
{{template "base/alert" .}}
<div class="small-pill-buttons ui compact tiny menu">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/projects?state=open">
{{svg "octicon-project" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
</a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/projects?state=closed">
{{svg "octicon-check" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .ClosedCount}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
</a>
</div>
<div class="ui right floated secondary filter menu">
<!-- Sort -->
<div class="ui dropdown type jump item">
<span class="text">
{{.locale.Tr "repo.issues.filter_sort"}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span>
<div class="menu">
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=oldest&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=recentupdate&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=leastupdate&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
<div class="navbar gt-mb-4">
<div>
<div class="small-menu-items ui compact tiny menu">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/projects?state=open">
{{svg "octicon-project" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}
</a>
<a class="item{{if .IsShowClosed}} active{{end}}" href="{{.RepoLink}}/projects?state=closed">
{{svg "octicon-check" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .ClosedCount}}&nbsp;{{.locale.Tr "repo.issues.closed_title"}}
</a>
</div>
</div>
<div>
<!-- Sort -->
<div class="ui small dropdown type jump item">
<span class="text">
{{.locale.Tr "repo.issues.filter_sort"}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</span>
<div class="menu">
<a class="{{if eq .SortType "oldest"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=oldest&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.oldest"}}</a>
<a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=recentupdate&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.recentupdate"}}</a>
<a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="{{$.Link}}?q={{$.Keyword}}&sort=leastupdate&state={{$.State}}">{{.locale.Tr "repo.issues.filter_sort.leastupdate"}}</a>
</div>
</div>
{{if and .CanWriteProjects (not .Repository.IsArchived)}}
<a class="ui small green button gt-ml-4" href="{{$.Link}}/new">{{.locale.Tr "repo.projects.new"}}</a>
{{end}}
</div>
</div>
{{template "base/alert" .}}
<div class="milestone list">
{{range .Projects}}
<li class="item">

View File

@ -2,18 +2,9 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository view issue pull commits">
{{template "repo/header" .}}
<div class="ui container">
<div class="navbar">
{{template "repo/issue/navbar" .}}
<div class="ui right">
<a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | PathEscapeSegments}}...{{.PullRequestCtx.HeadInfoSubURL}}">{{.locale.Tr "repo.pulls.new"}}</a>
</div>
</div>
<div class="ui divider"></div>
{{template "repo/issue/view_title" .}}
{{template "repo/pulls/tab_menu" .}}
<div class="ui bottom attached tab pull active">
{{template "repo/commits_table" .}}
</div>
{{template "repo/commits_table" .}}
</div>
</div>
{{template "base/footer" .}}

View File

@ -5,20 +5,10 @@
<div role="main" aria-label="{{.Title}}" class="page-content repository view issue pull files diff">
{{template "repo/header" .}}
<div class="ui container fluid padded">
<div class="navbar">
{{template "repo/issue/navbar" .}}
<div class="ui right">
<a class="ui green button {{if not .PullRequestCtx.Allowed}}disabled{{end}}" href="{{.RepoLink}}/compare/{{.BranchName | PathEscapeSegments}}...{{.PullRequestCtx.HeadInfoSubURL}}">{{.locale.Tr "repo.pulls.new"}}</a>
</div>
</div>
<div class="ui divider"></div>
<div class="ui container">
{{template "repo/issue/view_title" .}}
{{template "repo/pulls/tab_menu" .}}
{{template "base/alert" .}}
<div class="ui bottom attached tab pull active">
{{template "repo/diff/box" .}}
</div>
{{template "repo/diff/box" .}}
</div>
</div>
{{template "base/footer" .}}

View File

@ -14,13 +14,11 @@
<ul id="release-list">
{{range $idx, $release := .Releases}}
<li class="ui grid">
<div class="ui four wide column meta gt-mt-2">
<a class="gt-df gt-ac gt-je muted" href="{{if not .Sha1}}#{{else}}{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}{{end}}" rel="nofollow">{{svg "octicon-tag" 16 "gt-mr-2"}}{{.TagName}}</a>
<div class="ui four wide column meta">
<a class="gt-db muted" href="{{if not .Sha1}}#{{else}}{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}{{end}}" rel="nofollow">{{svg "octicon-tag" 16 "gt-mr-2"}}{{.TagName}}</a>
{{if .Sha1}}
<span class="commit">
<a class="gt-mono muted" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "gt-mr-2"}}{{ShortSha .Sha1}}</a>
</span>
{{template "repo/branch_dropdown" dict "root" $ "release" .}}
<a class="gt-mono muted gt-db gt-mt-4 gt-pt-1" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "gt-mr-2"}}{{ShortSha .Sha1}}</a>
{{template "repo/branch_dropdown" dict "root" $ "release" . "ContainerClasses" "gt-mt-4"}}
{{end}}
</div>
<div class="ui twelve wide column detail">

View File

@ -91,7 +91,7 @@
<td>{{$.locale.Tr "repo.settings.mirror_settings.direction.pull"}}</td>
<td>{{DateTime "full" .Mirror.UpdatedUnix}}</td>
<td class="right aligned">
<form method="post" style="display: inline-block">
<form method="post gt-dib">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="mirror-sync">
<button class="ui primary tiny button inline text-thin">{{$.locale.Tr "repo.settings.sync_mirror"}}</button>
@ -169,13 +169,13 @@
<td>{{$.locale.Tr "repo.settings.mirror_settings.direction.push"}}</td>
<td>{{if .LastUpdateUnix}}{{DateTime "full" .LastUpdateUnix}}{{else}}{{$.locale.Tr "never"}}{{end}} {{if .LastError}}<div class="ui red label" data-tooltip-content="{{.LastError}}">{{$.locale.Tr "error"}}</div>{{end}}</td>
<td class="right aligned">
<form method="post" style="display: inline-block">
<form method="post gt-dib">
{{$.CsrfTokenHtml}}
<input type="hidden" name="action" value="push-mirror-remove">
<input type="hidden" name="push_mirror_id" value="{{.ID}}">
<button class="ui basic red tiny button inline text-thin">{{$.locale.Tr "remove"}}</button>
</form>
<form method="post" style="display: inline-block">
<form method="post gt-dib">
{{$.CsrfTokenHtml}}
<input type="hidden" name="action" value="push-mirror-sync">
<input type="hidden" name="push_mirror_id" value="{{.ID}}">
@ -803,7 +803,7 @@
{{.locale.Tr "repo.settings.convert"}}
</div>
<div class="content">
<div class="ui warning message text left">
<div class="ui warning message">
{{.locale.Tr "repo.settings.convert_notices_1"}}
</div>
<form class="ui form" action="{{.Link}}" method="post">
@ -834,7 +834,7 @@
{{.locale.Tr "repo.settings.convert_fork"}}
</div>
<div class="content">
<div class="ui warning message text left">
<div class="ui warning message">
{{.locale.Tr "repo.settings.convert_fork_notices_1"}}
</div>
<form class="ui form" action="{{.Link}}" method="post">
@ -864,7 +864,7 @@
{{.locale.Tr "repo.settings.transfer"}}
</div>
<div class="content">
<div class="ui warning message text left">
<div class="ui warning message">
{{.locale.Tr "repo.settings.transfer_notices_1"}} <br>
{{.locale.Tr "repo.settings.transfer_notices_2"}} <br>
{{.locale.Tr "repo.settings.transfer_notices_3"}}
@ -900,7 +900,7 @@
{{.locale.Tr "repo.settings.delete"}}
</div>
<div class="content">
<div class="ui warning message text left">
<div class="ui warning message">
{{.locale.Tr "repo.settings.delete_notices_1" | Safe}}<br>
{{.locale.Tr "repo.settings.delete_notices_2" .Repository.FullName | Safe}}
{{if .Repository.NumForks}}<br>
@ -935,7 +935,7 @@
{{.locale.Tr "repo.settings.wiki_delete"}}
</div>
<div class="content">
<div class="ui warning message text left">
<div class="ui warning message">
{{.locale.Tr "repo.settings.delete_notices_1" | Safe}}<br>
{{.locale.Tr "repo.settings.wiki_delete_notices_1" .Repository.Name | Safe}}
</div>

View File

@ -21,7 +21,7 @@
<a class="ui primary sha label toggle button show-panel" data-panel="#info-{{.ID}}">{{.UUID}}</a>
<div class="ui right">
<span class="text grey time">
{{.DeliveredString}}
{{TimeSince .Delivered.AsTime $.locale}}
</span>
</div>
</div>

View File

@ -2,7 +2,7 @@
{{$canReadCode := $.Permission.CanRead $.UnitTypeCode}}
{{if $canReadReleases}}
<h2 class="ui compact small menu header small-pill-buttons">
<h2 class="ui compact small menu header small-menu-items">
<a class="{{if .PageIsReleaseList}}active {{end}}item" href="{{.RepoLink}}/releases">{{.locale.Tr "repo.release.releases"}}</a>
{{if $canReadCode}}
<a class="{{if .PageIsTagList}}active {{end}}item" href="{{.RepoLink}}/tags">{{.locale.Tr "repo.release.tags"}}</a>

View File

@ -61,7 +61,7 @@
</div>
<div class="twelve wide column content">
<div class="list-header">
<div class="small-pill-buttons ui compact tiny menu">
<div class="small-menu-items ui compact tiny menu">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.Link}}?type={{$.ViewType}}&repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=open&q={{$.Keyword}}">
{{svg "octicon-issue-opened" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .IssueStats.OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}

View File

@ -35,7 +35,7 @@
</div>
<div class="twelve wide column content">
<div class="list-header">
<div class="small-pill-buttons ui compact tiny menu">
<div class="small-menu-items ui compact tiny menu">
<a class="item{{if not .IsShowClosed}} active{{end}}" href="{{.Link}}?repos=[{{range $.RepoIDs}}{{.}}%2C{{end}}]&sort={{$.SortType}}&state=open&q={{$.Keyword}}">
{{svg "octicon-milestone" 16 "gt-mr-3"}}
{{.locale.PrettyNumber .MilestoneStats.OpenCount}}&nbsp;{{.locale.Tr "repo.issues.open_title"}}

View File

@ -13,7 +13,7 @@
{{if eq .Status 1}}
<div class="ui stackable grid">
<div class="six wide column">
<div class="small-pill-buttons ui compact tiny menu">
<div class="small-menu-items ui compact tiny menu">
<a class="{{if eq .State "all"}}active {{end}}item" href="{{$.Link}}?sort={{$.SortType}}&state=all&issueType={{$.IssueType}}&labels={{$.Labels}}">
{{.locale.Tr "all"}}
</a>

View File

@ -98,7 +98,7 @@ func testPackageCargo(t *testing.T, _ *neturl.URL) {
url := fmt.Sprintf("%s/api/v1/crates", root)
t.Run("Index", func(t *testing.T) {
t.Run("Config", func(t *testing.T) {
t.Run("Git/Config", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
content := readGitContent(t, cargo_service.ConfigFileName)
@ -110,6 +110,20 @@ func testPackageCargo(t *testing.T, _ *neturl.URL) {
assert.Equal(t, url, config.DownloadURL)
assert.Equal(t, root, config.APIURL)
})
t.Run("HTTP/Config", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", root+"/"+cargo_service.ConfigFileName)
resp := MakeRequest(t, req, http.StatusOK)
var config cargo_service.Config
err := json.Unmarshal(resp.Body.Bytes(), &config)
assert.NoError(t, err)
assert.Equal(t, url, config.DownloadURL)
assert.Equal(t, root, config.APIURL)
})
})
t.Run("Upload", func(t *testing.T) {
@ -192,40 +206,72 @@ func testPackageCargo(t *testing.T, _ *neturl.URL) {
MakeRequest(t, req, http.StatusConflict)
t.Run("Index", func(t *testing.T) {
t.Run("Entry", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
t.Run("Git", func(t *testing.T) {
t.Run("Entry", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
content := readGitContent(t, cargo_service.BuildPackagePath(packageName))
content := readGitContent(t, cargo_service.BuildPackagePath(packageName))
var entry cargo_service.IndexVersionEntry
err := json.Unmarshal([]byte(content), &entry)
assert.NoError(t, err)
var entry cargo_service.IndexVersionEntry
err := json.Unmarshal([]byte(content), &entry)
assert.NoError(t, err)
assert.Equal(t, packageName, entry.Name)
assert.Equal(t, packageVersion, entry.Version)
assert.Equal(t, pb.HashSHA256, entry.FileChecksum)
assert.False(t, entry.Yanked)
assert.Len(t, entry.Dependencies, 1)
dep := entry.Dependencies[0]
assert.Equal(t, "dep", dep.Name)
assert.Equal(t, "1.0", dep.Req)
assert.Equal(t, "normal", dep.Kind)
assert.True(t, dep.DefaultFeatures)
assert.Empty(t, dep.Features)
assert.False(t, dep.Optional)
assert.Nil(t, dep.Target)
assert.NotNil(t, dep.Registry)
assert.Equal(t, "https://gitea.io/user/_cargo-index", *dep.Registry)
assert.Nil(t, dep.Package)
assert.Equal(t, packageName, entry.Name)
assert.Equal(t, packageVersion, entry.Version)
assert.Equal(t, pb.HashSHA256, entry.FileChecksum)
assert.False(t, entry.Yanked)
assert.Len(t, entry.Dependencies, 1)
dep := entry.Dependencies[0]
assert.Equal(t, "dep", dep.Name)
assert.Equal(t, "1.0", dep.Req)
assert.Equal(t, "normal", dep.Kind)
assert.True(t, dep.DefaultFeatures)
assert.Empty(t, dep.Features)
assert.False(t, dep.Optional)
assert.Nil(t, dep.Target)
assert.NotNil(t, dep.Registry)
assert.Equal(t, "https://gitea.io/user/_cargo-index", *dep.Registry)
assert.Nil(t, dep.Package)
})
t.Run("Rebuild", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
err := cargo_service.RebuildIndex(db.DefaultContext, user, user)
assert.NoError(t, err)
_ = readGitContent(t, cargo_service.BuildPackagePath(packageName))
})
})
t.Run("Rebuild", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
t.Run("HTTP", func(t *testing.T) {
t.Run("Entry", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
err := cargo_service.RebuildIndex(db.DefaultContext, user, user)
assert.NoError(t, err)
req := NewRequest(t, "GET", root+"/"+cargo_service.BuildPackagePath(packageName))
resp := MakeRequest(t, req, http.StatusOK)
_ = readGitContent(t, cargo_service.BuildPackagePath(packageName))
var entry cargo_service.IndexVersionEntry
err := json.Unmarshal(resp.Body.Bytes(), &entry)
assert.NoError(t, err)
assert.Equal(t, packageName, entry.Name)
assert.Equal(t, packageVersion, entry.Version)
assert.Equal(t, pb.HashSHA256, entry.FileChecksum)
assert.False(t, entry.Yanked)
assert.Len(t, entry.Dependencies, 1)
dep := entry.Dependencies[0]
assert.Equal(t, "dep", dep.Name)
assert.Equal(t, "1.0", dep.Req)
assert.Equal(t, "normal", dep.Kind)
assert.True(t, dep.DefaultFeatures)
assert.Empty(t, dep.Features)
assert.False(t, dep.Optional)
assert.Nil(t, dep.Target)
assert.NotNil(t, dep.Registry)
assert.Equal(t, "https://gitea.io/user/_cargo-index", *dep.Registry)
assert.Nil(t, dep.Package)
})
})
})
})

View File

@ -143,7 +143,7 @@ func testNewIssue(t *testing.T, session *TestSession, user, repo, title, content
htmlDoc = NewHTMLParser(t, resp.Body)
val := htmlDoc.doc.Find("#issue-title").Text()
assert.Equal(t, title, val)
assert.Contains(t, val, title)
val = htmlDoc.doc.Find(".comment .render-content p").First().Text()
assert.Equal(t, content, val)

View File

@ -57,7 +57,7 @@ func initMigrationTest(t *testing.T) func() {
setting.CustomConf = giteaConf
}
setting.InitProviderAndLoadCommonSettingsForTest()
unittest.InitSettings()
assert.True(t, len(setting.RepoRootPath) != 0)
assert.NoError(t, util.RemoveAll(setting.RepoRootPath))

View File

@ -74,7 +74,7 @@ func InitTest(requireGitea bool) {
}
setting.SetCustomPathAndConf("", "", "")
setting.InitProviderAndLoadCommonSettingsForTest()
unittest.InitSettings()
setting.Repository.DefaultBranch = "master" // many test code still assume that default branch is called "master"
_ = util.RemoveAll(repo_module.LocalCopyPath())

View File

@ -1556,7 +1556,7 @@ img.ui.avatar,
vertical-align: middle;
}
.ui .message {
.ui .message.flash-message {
text-align: center;
}
@ -2559,18 +2559,18 @@ a.ui.basic.label:hover {
.notification_count {
position: absolute;
left: 5px;
top: -8px;
left: 7px;
top: -9px;
min-width: 1.5em;
text-align: center;
background: var(--color-primary);
border: 2px solid var(--color-header-bar);
color: var(--color-header-bar);
padding: 2px;
padding: 2.75px;
border-radius: 1em;
font-size: 10px;
font-size: 11px;
font-weight: 700;
line-height: 0.7;
line-height: .67em;
}
table th[data-sortt-asc]:hover,

View File

@ -41,6 +41,5 @@
@import "./admin.css";
@import "./explore.css";
@import "./review.css";
@import "./package.css";
@import "./runner.css";
@import "./helpers.css";

View File

@ -1,7 +0,0 @@
.container-labels td:nth-child(1) {
vertical-align: top;
}
.container-labels td:nth-child(2) {
overflow-wrap: anywhere;
}

View File

@ -591,87 +591,83 @@
display: inline-block;
}
.repository.view.issue .title {
padding-bottom: 0 !important;
.issue-title-header {
width: 100%;
padding-bottom: 4px;
margin-bottom: 1rem;
}
.repository.view.issue .title .issue-title {
margin-bottom: 0.5rem;
}
.repository.view.issue .title .issue-title.edit-active {
.issue-title-meta {
display: flex;
align-items: center;
}
.repository.view.issue .title .issue-title.edit-active h1 {
.repository.view.issue .issue-title-buttons,
.repository.view.issue .edit-buttons {
display: flex;
width: 100%;
}
@media (max-width: 767px) {
.repository.view.issue .title .issue-title.edit-active {
.repository.view.issue .issue-title {
flex-direction: column;
}
.repository.view.issue .title .issue-title.edit-active h1 {
margin-right: 0;
margin-bottom: 1rem;
padding-right: 0;
}
.repository.view.issue .title .issue-title.edit-active h1 .ui.input input {
width: calc(100% - 2rem);
}
.repository.view.issue .title .issue-title.edit-active .edit-buttons {
padding-bottom: 1rem;
width: 100%;
}
.repository.view.issue .title .issue-title.edit-active .edit-buttons .button {
width: 100%;
margin-right: 0.5rem;
}
.repository.view.issue .title .issue-title.edit-active .edit-buttons .button:last-child {
margin-right: 0;
.repository.view.issue .edit-buttons {
margin-top: .5rem;
}
}
.repository.view.issue .title .issue-title h1 {
font-weight: 300;
font-size: 2.3rem;
margin: 0;
padding-right: 0.5rem;
}
.repository.view.issue .title .issue-title h1 .ui.input {
font-size: 0.5em;
width: 100%;
}
.repository.view.issue .title .issue-title h1 .ui.input input {
font-size: 1.5em;
padding: 6px 1rem;
}
.repository.view.issue .title .issue-title .edit-button {
float: right;
padding-left: 1rem;
}
.repository.view.issue .title .issue-title .edit-buttons {
.repository.view.issue .issue-title {
display: flex;
align-items: center;
margin-bottom: 8px;
}
.repository.view.issue .title .issue-title .index {
.repository.view.issue .issue-title h1 {
display: flex;
align-items: center;
flex: 1;
width: 100%;
font-weight: 300;
font-size: 32px;
line-height: 40px;
margin: 0;
padding-right: 0.25rem;
min-height: 41px; /* avoid layout shift on edit */
}
.repository.view.issue .issue-title h1 .ui.input {
font-size: 0.5em;
}
.repository.view.issue .issue-title h1 .ui.input input {
font-size: 1.5em;
padding: 2px .5rem;
}
.repository.view.issue .issue-title .index {
color: var(--color-text-light-2);
}
.repository.view.issue .title .issue-title .label {
.repository.view.issue .issue-title .label {
margin-right: 10px;
}
.repository.view.issue .title .issue-title .edit-zone {
.repository.view.issue .issue-title .edit-zone {
margin-top: 10px;
}
.issue-state-label {
display: flex !important;
align-items: center !important;
font-size: 14px !important;
padding: 7px 10px !important;
border-radius: 6px !important;
}
.issue-state-label .svg {
margin-right: 4px;
}
.repository.view.issue .pull-desc code {
color: var(--color-primary);
}
@ -1193,13 +1189,15 @@
.repository .milestone.list {
list-style: none;
padding-top: 15px;
}
.repository .milestone.list > .item {
padding-top: 10px;
padding-bottom: 10px;
border-bottom: 1px dashed var(--color-secondary);
}
.repository .milestone.list > .item + .item {
border-top: 1px solid var(--color-secondary);
}
.repository .milestone.list > .item progress {
@ -2600,39 +2598,6 @@
height: 15px;
}
#avatar-arrow::before,
#avatar-arrow::after {
right: 100%;
top: 20px;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
#avatar-arrow::before {
border-right-color: var(--color-secondary);
border-width: 9px;
margin-top: -9px;
}
#avatar-arrow::after {
border-right-color: var(--color-box-header);
border-width: 8px;
margin-top: -8px;
}
#transfer-repo-modal .ui.message,
#delete-repo-modal .ui.message,
#delete-wiki-modal .ui.message,
#convert-fork-repo-modal .ui.message,
#convert-mirror-repo-modal .ui.message,
#fork-repo-modal .ui.message {
width: 100% !important;
}
.tab-size-1 {
tab-size: 1 !important;
-moz-tab-size: 1 !important;

View File

@ -3,6 +3,7 @@
flex-wrap: wrap;
align-items: flex-start;
gap: 1rem;
margin-top: 1rem;
}
.issue-list-toolbar-left {

View File

@ -26,11 +26,11 @@
flex: 1;
}
.small-pill-buttons {
.small-menu-items {
min-height: 35.4px !important; /* match .small.button in height */
}
.small-pill-buttons .item {
.small-menu-items .item {
padding-top: 6px !important;
padding-bottom: 6px !important;
}

View File

@ -1,7 +1,6 @@
.repository.releases #release-list {
border-top: 1px solid var(--color-secondary);
margin-top: 20px;
padding-top: 15px;
margin-top: 12px;
padding-top: 12px;
padding-left: 0;
}
@ -23,29 +22,13 @@
}
.repository.releases #release-list > li .meta {
margin-top: 4px;
text-align: right;
position: relative;
}
.repository.releases #release-list > li .meta .label {
margin-right: 0;
}
.repository.releases #release-list > li .meta .commit {
display: block;
margin-top: 10px;
}
.repository.releases #release-list > li .meta .choose {
margin-top: 15px;
}
.repository.releases #release-list > li .meta .choose .button {
margin-right: 0;
}
.repository.releases #release-list > li .detail {
border-left: 2px solid var(--color-secondary);
border-left: 1px solid var(--color-secondary);
}
.repository.releases #release-list > li .detail .author img {
@ -92,7 +75,7 @@
z-index: 9;
position: absolute;
display: block;
left: -6px;
left: -5.5px;
top: 40px;
border-radius: 100%;
border: 2.5px solid var(--color-body);

View File

@ -29,33 +29,33 @@
--color-primary-alpha-70: #87ab63b3;
--color-primary-alpha-80: #87ab63cc;
--color-primary-alpha-90: #87ab63e1;
--color-secondary: #454a57;
--color-secondary-dark-1: #505665;
--color-secondary-dark-2: #5b6273;
--color-secondary-dark-3: #71798e;
--color-secondary-dark-4: #7f8699;
--color-secondary-dark-5: #8c93a4;
--color-secondary-dark-6: #9aa0af;
--color-secondary-dark-7: #a8adba;
--color-secondary-dark-8: #b6bac5;
--color-secondary-dark-9: #c4c7d0;
--color-secondary-dark-10: #d2d4db;
--color-secondary-dark-11: #dfe1e6;
--color-secondary-dark-12: #edeef1;
--color-secondary: #525767;
--color-secondary-dark-1: #5c6374;
--color-secondary-dark-2: #666e81;
--color-secondary-dark-3: #7c8497;
--color-secondary-dark-4: #8990a1;
--color-secondary-dark-5: #959cab;
--color-secondary-dark-6: #a2a8b5;
--color-secondary-dark-7: #afb4c0;
--color-secondary-dark-8: #bcc0ca;
--color-secondary-dark-9: #c9cbd4;
--color-secondary-dark-10: #d6d7de;
--color-secondary-dark-11: #e2e3e8;
--color-secondary-dark-12: #eeeff2;
--color-secondary-dark-13: #fbfbfc;
--color-secondary-light-1: #373b46;
--color-secondary-light-2: #292c34;
--color-secondary-light-3: #1c1e23;
--color-secondary-light-4: #0e0f11;
--color-secondary-alpha-10: #454a5719;
--color-secondary-alpha-20: #454a5733;
--color-secondary-alpha-30: #454a574b;
--color-secondary-alpha-40: #454a5766;
--color-secondary-alpha-50: #454a5780;
--color-secondary-alpha-60: #454a5799;
--color-secondary-alpha-70: #454a57b3;
--color-secondary-alpha-80: #454a57cc;
--color-secondary-alpha-90: #454a57e1;
--color-secondary-light-1: #454a57;
--color-secondary-light-2: #383c47;
--color-secondary-light-3: #2c2f37;
--color-secondary-light-4: #1f2226;
--color-secondary-alpha-10: #52576719;
--color-secondary-alpha-20: #52576733;
--color-secondary-alpha-30: #5257674b;
--color-secondary-alpha-40: #52576766;
--color-secondary-alpha-50: #52576780;
--color-secondary-alpha-60: #52576799;
--color-secondary-alpha-70: #525767b3;
--color-secondary-alpha-80: #525767cc;
--color-secondary-alpha-90: #525767e1;
/* colors */
--color-red: #cc4848;
--color-orange: #cc580c;

View File

@ -1,6 +1,6 @@
<template>
<div class="ui floating filter dropdown custom">
<button class="branch-dropdown-button gt-ellipsis ui basic small compact button gt-df" @click="menuVisible = !menuVisible" @keyup.enter="menuVisible = !menuVisible">
<button class="branch-dropdown-button gt-ellipsis ui basic small compact button gt-df gt-m-0" @click="menuVisible = !menuVisible" @keyup.enter="menuVisible = !menuVisible">
<span class="text gt-df gt-ac gt-mr-2">
<template v-if="release">{{ textReleaseCompare }}</template>
<template v-else>

View File

@ -8,7 +8,7 @@ import {handleGlobalEnterQuickSubmit} from './QuickSubmit.js';
import {emojiString} from '../emoji.js';
import {renderPreviewPanelContent} from '../repo-editor.js';
import {matchEmoji, matchMention} from '../../utils/match.js';
import {svg} from '../../svg.js';
import {easyMDEToolbarActions} from './EasyMDEToolbarActions.js';
let elementIdCounter = 0;
@ -206,66 +206,20 @@ class ComboMarkdownEditor {
prepareEasyMDEToolbarActions() {
this.easyMDEToolbarDefault = [
'bold', 'italic', 'strikethrough', '|', 'heading-1', 'heading-2', 'heading-3', 'heading-bigger', 'heading-smaller', '|',
'code', 'quote', '|', 'gitea-checkbox-empty', 'gitea-checkbox-checked', '|',
'unordered-list', 'ordered-list', '|', 'link', 'image', 'table', 'horizontal-rule', '|', 'clean-block', '|',
'gitea-switch-to-textarea',
'bold', 'italic', 'strikethrough', '|', 'heading-1', 'heading-2', 'heading-3',
'heading-bigger', 'heading-smaller', '|', 'code', 'quote', '|', 'gitea-checkbox-empty',
'gitea-checkbox-checked', '|', 'unordered-list', 'ordered-list', '|', 'link', 'image',
'table', 'horizontal-rule', '|', 'gitea-switch-to-textarea',
];
this.easyMDEToolbarActions = {
'gitea-checkbox-empty': {
action(e) {
const cm = e.codemirror;
cm.replaceSelection(`\n- [ ] ${cm.getSelection()}`);
cm.focus();
},
icon: svg('gitea-empty-checkbox'),
title: 'Add Checkbox (empty)',
},
'gitea-checkbox-checked': {
action(e) {
const cm = e.codemirror;
cm.replaceSelection(`\n- [x] ${cm.getSelection()}`);
cm.focus();
},
icon: svg('octicon-checkbox'),
title: 'Add Checkbox (checked)',
},
'gitea-switch-to-textarea': {
action: () => {
this.userPreferredEditor = 'textarea';
this.switchToTextarea();
},
icon: svg('octicon-file'),
title: 'Revert to simple textarea',
},
'gitea-code-inline': {
action(e) {
const cm = e.codemirror;
const selection = cm.getSelection();
cm.replaceSelection(`\`${selection}\``);
if (!selection) {
const cursorPos = cm.getCursor();
cm.setCursor(cursorPos.line, cursorPos.ch - 1);
}
cm.focus();
},
icon: svg('octicon-chevron-right'),
title: 'Add Inline Code',
}
};
}
parseEasyMDEToolbar(actions) {
parseEasyMDEToolbar(EasyMDE, actions) {
this.easyMDEToolbarActions = this.easyMDEToolbarActions || easyMDEToolbarActions(EasyMDE, this);
const processed = [];
for (const action of actions) {
if (action.startsWith('gitea-')) {
const giteaAction = this.easyMDEToolbarActions[action];
if (!giteaAction) throw new Error(`Unknown EasyMDE toolbar action ${action}`);
processed.push(giteaAction);
} else {
processed.push(action);
}
const actionButton = this.easyMDEToolbarActions[action];
if (!actionButton) throw new Error(`Unknown EasyMDE toolbar action ${action}`);
processed.push(actionButton);
}
return processed;
}
@ -293,7 +247,7 @@ class ComboMarkdownEditor {
nativeSpellcheck: true,
...this.options.easyMDEOptions,
};
easyMDEOpt.toolbar = this.parseEasyMDEToolbar(easyMDEOpt.toolbar ?? this.easyMDEToolbarDefault);
easyMDEOpt.toolbar = this.parseEasyMDEToolbar(EasyMDE, easyMDEOpt.toolbar ?? this.easyMDEToolbarDefault);
this.easyMDE = new EasyMDE(easyMDEOpt);
this.easyMDE.codemirror.on('change', (...args) => {this.options?.onContentChanged?.(this, ...args)});

View File

@ -0,0 +1,152 @@
import {svg} from '../../svg.js';
export function easyMDEToolbarActions(EasyMDE, editor) {
const actions = {
'|': '|',
'heading-1': {
action: EasyMDE.toggleHeading1,
icon: svg('octicon-heading'),
title: 'Heading 1',
},
'heading-2': {
action: EasyMDE.toggleHeading2,
icon: svg('octicon-heading'),
title: 'Heading 2',
},
'heading-3': {
action: EasyMDE.toggleHeading3,
icon: svg('octicon-heading'),
title: 'Heading 3',
},
'heading-smaller': {
action: EasyMDE.toggleHeadingSmaller,
icon: svg('octicon-heading'),
title: 'Decrease Heading',
},
'heading-bigger': {
action: EasyMDE.toggleHeadingBigger,
icon: svg('octicon-heading'),
title: 'Increase Heading',
},
'bold': {
action: EasyMDE.toggleBold,
icon: svg('octicon-bold'),
title: 'Bold',
},
'italic': {
action: EasyMDE.toggleItalic,
icon: svg('octicon-italic'),
title: 'Italic',
},
'strikethrough': {
action: EasyMDE.toggleStrikethrough,
icon: svg('octicon-strikethrough'),
title: 'Strikethrough',
},
'quote': {
action: EasyMDE.toggleBlockquote,
icon: svg('octicon-quote'),
title: 'Quote',
},
'code': {
action: EasyMDE.toggleCodeBlock,
icon: svg('octicon-code'),
title: 'Code',
},
'link': {
action: EasyMDE.drawLink,
icon: svg('octicon-link'),
title: 'Link',
},
'unordered-list': {
action: EasyMDE.toggleUnorderedList,
icon: svg('octicon-list-unordered'),
title: 'Unordered List',
},
'ordered-list': {
action: EasyMDE.toggleOrderedList,
icon: svg('octicon-list-ordered'),
title: 'Ordered List',
},
'image': {
action: EasyMDE.drawImage,
icon: svg('octicon-image'),
title: 'Image',
},
'table': {
action: EasyMDE.drawTable,
icon: svg('octicon-table'),
title: 'Table',
},
'horizontal-rule': {
action: EasyMDE.drawHorizontalRule,
icon: svg('octicon-horizontal-rule'),
title: 'Horizontal Rule',
},
'preview': {
action: EasyMDE.togglePreview,
icon: svg('octicon-eye'),
title: 'Preview',
},
'fullscreen': {
action: EasyMDE.toggleFullScreen,
icon: svg('octicon-screen-full'),
title: 'Fullscreen',
},
'side-by-side': {
action: EasyMDE.toggleSideBySide,
icon: svg('octicon-columns'),
title: 'Side by Side',
},
// gitea's custom actions
'gitea-checkbox-empty': {
action(e) {
const cm = e.codemirror;
cm.replaceSelection(`\n- [ ] ${cm.getSelection()}`);
cm.focus();
},
icon: svg('gitea-empty-checkbox'),
title: 'Add Checkbox (empty)',
},
'gitea-checkbox-checked': {
action(e) {
const cm = e.codemirror;
cm.replaceSelection(`\n- [x] ${cm.getSelection()}`);
cm.focus();
},
icon: svg('octicon-checkbox'),
title: 'Add Checkbox (checked)',
},
'gitea-switch-to-textarea': {
action: () => {
editor.userPreferredEditor = 'textarea';
editor.switchToTextarea();
},
icon: svg('octicon-arrow-switch'),
title: 'Revert to simple textarea',
},
'gitea-code-inline': {
action(e) {
const cm = e.codemirror;
const selection = cm.getSelection();
cm.replaceSelection(`\`${selection}\``);
if (!selection) {
const cursorPos = cm.getCursor();
cm.setCursor(cursorPos.line, cursorPos.ch - 1);
}
cm.focus();
},
icon: svg('octicon-chevron-right'),
title: 'Add Inline Code',
}
};
for (const [key, value] of Object.entries(actions)) {
if (typeof value !== 'string') {
value.name = key;
}
}
return actions;
}

View File

@ -572,8 +572,10 @@ export function initRepoIssueTitleEdit() {
toggleElem($('#pull-desc'));
toggleElem($('#pull-desc-edit'));
toggleElem($('.in-edit'));
toggleElem($('.new-issue-button'));
$('#issue-title-wrapper').toggleClass('edit-active');
$editInput.trigger('focus');
$editInput[0].focus();
$editInput[0].select();
return false;
};

View File

@ -469,11 +469,7 @@ export function initRepository() {
return;
}
// File list and commits
if ($('.repository.file.list').length > 0 || $('.branch-dropdown').length > 0 ||
$('.repository.commits').length > 0 || $('.repository.release').length > 0) {
initRepoBranchTagSelector('.js-branch-tag-selector');
}
initRepoBranchTagSelector('.js-branch-tag-selector');
// Options
if ($('.repository.settings.options').length > 0) {

View File

@ -58,7 +58,7 @@ async function initRepoWikiFormEditor() {
'gitea-code-inline', 'code', 'quote', '|', 'gitea-checkbox-empty', 'gitea-checkbox-checked', '|',
'unordered-list', 'ordered-list', '|',
'link', 'image', 'table', 'horizontal-rule', '|',
'clean-block', 'preview', 'fullscreen', 'side-by-side', '|', 'gitea-switch-to-textarea'
'preview', 'fullscreen', 'side-by-side', '|', 'gitea-switch-to-textarea'
],
},
});

View File

@ -1,80 +1,106 @@
import {h} from 'vue';
import giteaDoubleChevronLeft from '../../public/img/svg/gitea-double-chevron-left.svg';
import giteaDoubleChevronRight from '../../public/img/svg/gitea-double-chevron-right.svg';
import giteaEmptyCheckbox from '../../public/img/svg/gitea-empty-checkbox.svg';
import octiconArchive from '../../public/img/svg/octicon-archive.svg';
import octiconArrowSwitch from '../../public/img/svg/octicon-arrow-switch.svg';
import octiconBlocked from '../../public/img/svg/octicon-blocked.svg';
import octiconBold from '../../public/img/svg/octicon-bold.svg';
import octiconCheckbox from '../../public/img/svg/octicon-checkbox.svg';
import octiconCheckCircleFill from '../../public/img/svg/octicon-check-circle-fill.svg';
import octiconChevronDown from '../../public/img/svg/octicon-chevron-down.svg';
import octiconChevronLeft from '../../public/img/svg/octicon-chevron-left.svg';
import octiconChevronRight from '../../public/img/svg/octicon-chevron-right.svg';
import octiconClock from '../../public/img/svg/octicon-clock.svg';
import octiconCode from '../../public/img/svg/octicon-code.svg';
import octiconColumns from '../../public/img/svg/octicon-columns.svg';
import octiconCopy from '../../public/img/svg/octicon-copy.svg';
import octiconDiffAdded from '../../public/img/svg/octicon-diff-added.svg';
import octiconDiffModified from '../../public/img/svg/octicon-diff-modified.svg';
import octiconDiffRemoved from '../../public/img/svg/octicon-diff-removed.svg';
import octiconDiffRenamed from '../../public/img/svg/octicon-diff-renamed.svg';
import octiconEye from '../../public/img/svg/octicon-eye.svg';
import octiconFile from '../../public/img/svg/octicon-file.svg';
import octiconFileDirectoryFill from '../../public/img/svg/octicon-file-directory-fill.svg';
import octiconFilter from '../../public/img/svg/octicon-filter.svg';
import octiconGitBranch from '../../public/img/svg/octicon-git-branch.svg';
import octiconGitMerge from '../../public/img/svg/octicon-git-merge.svg';
import octiconGitPullRequest from '../../public/img/svg/octicon-git-pull-request.svg';
import octiconHeading from '../../public/img/svg/octicon-heading.svg';
import octiconHorizontalRule from '../../public/img/svg/octicon-horizontal-rule.svg';
import octiconImage from '../../public/img/svg/octicon-image.svg';
import octiconIssueClosed from '../../public/img/svg/octicon-issue-closed.svg';
import octiconIssueOpened from '../../public/img/svg/octicon-issue-opened.svg';
import octiconItalic from '../../public/img/svg/octicon-italic.svg';
import octiconKebabHorizontal from '../../public/img/svg/octicon-kebab-horizontal.svg';
import octiconLink from '../../public/img/svg/octicon-link.svg';
import octiconListOrdered from '../../public/img/svg/octicon-list-ordered.svg';
import octiconListUnordered from '../../public/img/svg/octicon-list-unordered.svg';
import octiconLock from '../../public/img/svg/octicon-lock.svg';
import octiconMeter from '../../public/img/svg/octicon-meter.svg';
import octiconMilestone from '../../public/img/svg/octicon-milestone.svg';
import octiconMirror from '../../public/img/svg/octicon-mirror.svg';
import octiconOrganization from '../../public/img/svg/octicon-organization.svg';
import octiconPlay from '../../public/img/svg/octicon-play.svg';
import octiconPlus from '../../public/img/svg/octicon-plus.svg';
import octiconProject from '../../public/img/svg/octicon-project.svg';
import octiconQuote from '../../public/img/svg/octicon-quote.svg';
import octiconRepo from '../../public/img/svg/octicon-repo.svg';
import octiconRepoForked from '../../public/img/svg/octicon-repo-forked.svg';
import octiconRepoTemplate from '../../public/img/svg/octicon-repo-template.svg';
import octiconRss from '../../public/img/svg/octicon-rss.svg';
import octiconScreenFull from '../../public/img/svg/octicon-screen-full.svg';
import octiconSearch from '../../public/img/svg/octicon-search.svg';
import octiconSidebarCollapse from '../../public/img/svg/octicon-sidebar-collapse.svg';
import octiconSidebarExpand from '../../public/img/svg/octicon-sidebar-expand.svg';
import octiconSkip from '../../public/img/svg/octicon-skip.svg';
import octiconStar from '../../public/img/svg/octicon-star.svg';
import octiconStrikethrough from '../../public/img/svg/octicon-strikethrough.svg';
import octiconSync from '../../public/img/svg/octicon-sync.svg';
import octiconTable from '../../public/img/svg/octicon-table.svg';
import octiconTag from '../../public/img/svg/octicon-tag.svg';
import octiconTriangleDown from '../../public/img/svg/octicon-triangle-down.svg';
import octiconX from '../../public/img/svg/octicon-x.svg';
import octiconCheckCircleFill from '../../public/img/svg/octicon-check-circle-fill.svg';
import octiconXCircleFill from '../../public/img/svg/octicon-x-circle-fill.svg';
import octiconSkip from '../../public/img/svg/octicon-skip.svg';
import octiconMeter from '../../public/img/svg/octicon-meter.svg';
import octiconBlocked from '../../public/img/svg/octicon-blocked.svg';
import octiconSync from '../../public/img/svg/octicon-sync.svg';
import octiconFilter from '../../public/img/svg/octicon-filter.svg';
import octiconPlus from '../../public/img/svg/octicon-plus.svg';
import octiconSearch from '../../public/img/svg/octicon-search.svg';
import octiconArchive from '../../public/img/svg/octicon-archive.svg';
import octiconStar from '../../public/img/svg/octicon-star.svg';
import giteaDoubleChevronLeft from '../../public/img/svg/gitea-double-chevron-left.svg';
import giteaDoubleChevronRight from '../../public/img/svg/gitea-double-chevron-right.svg';
import octiconChevronLeft from '../../public/img/svg/octicon-chevron-left.svg';
import octiconOrganization from '../../public/img/svg/octicon-organization.svg';
import octiconTag from '../../public/img/svg/octicon-tag.svg';
import octiconGitBranch from '../../public/img/svg/octicon-git-branch.svg';
import octiconRss from '../../public/img/svg/octicon-rss.svg';
import octiconCheckbox from '../../public/img/svg/octicon-checkbox.svg';
import giteaEmptyCheckbox from '../../public/img/svg/gitea-empty-checkbox.svg';
const svgs = {
'gitea-double-chevron-left': giteaDoubleChevronLeft,
'gitea-double-chevron-right': giteaDoubleChevronRight,
'gitea-empty-checkbox': giteaEmptyCheckbox,
'octicon-archive': octiconArchive,
'octicon-arrow-switch': octiconArrowSwitch,
'octicon-blocked': octiconBlocked,
'octicon-checkbox': octiconCheckbox,
'octicon-bold': octiconBold,
'octicon-check-circle-fill': octiconCheckCircleFill,
'octicon-checkbox': octiconCheckbox,
'octicon-chevron-down': octiconChevronDown,
'octicon-chevron-left': octiconChevronLeft,
'octicon-chevron-right': octiconChevronRight,
'octicon-clock': octiconClock,
'octicon-code': octiconCode,
'octicon-columns': octiconColumns,
'octicon-copy': octiconCopy,
'octicon-diff-added': octiconDiffAdded,
'octicon-diff-modified': octiconDiffModified,
'octicon-diff-removed': octiconDiffRemoved,
'octicon-diff-renamed': octiconDiffRenamed,
'gitea-double-chevron-left': giteaDoubleChevronLeft,
'gitea-double-chevron-right': giteaDoubleChevronRight,
'gitea-empty-checkbox': giteaEmptyCheckbox,
'octicon-eye': octiconEye,
'octicon-file': octiconFile,
'octicon-file-directory-fill': octiconFileDirectoryFill,
'octicon-filter': octiconFilter,
'octicon-git-branch': octiconGitBranch,
'octicon-git-merge': octiconGitMerge,
'octicon-git-pull-request': octiconGitPullRequest,
'octicon-heading': octiconHeading,
'octicon-horizontal-rule': octiconHorizontalRule,
'octicon-image': octiconImage,
'octicon-issue-closed': octiconIssueClosed,
'octicon-issue-opened': octiconIssueOpened,
'octicon-italic': octiconItalic,
'octicon-kebab-horizontal': octiconKebabHorizontal,
'octicon-link': octiconLink,
'octicon-list-ordered': octiconListOrdered,
'octicon-list-unordered': octiconListUnordered,
'octicon-lock': octiconLock,
'octicon-meter': octiconMeter,
'octicon-milestone': octiconMilestone,
@ -83,16 +109,20 @@ const svgs = {
'octicon-play': octiconPlay,
'octicon-plus': octiconPlus,
'octicon-project': octiconProject,
'octicon-quote': octiconQuote,
'octicon-repo': octiconRepo,
'octicon-repo-forked': octiconRepoForked,
'octicon-repo-template': octiconRepoTemplate,
'octicon-rss': octiconRss,
'octicon-screen-full': octiconScreenFull,
'octicon-search': octiconSearch,
'octicon-sidebar-collapse': octiconSidebarCollapse,
'octicon-sidebar-expand': octiconSidebarExpand,
'octicon-skip': octiconSkip,
'octicon-star': octiconStar,
'octicon-strikethrough': octiconStrikethrough,
'octicon-sync': octiconSync,
'octicon-table': octiconTable,
'octicon-tag': octiconTag,
'octicon-triangle-down': octiconTriangleDown,
'octicon-x': octiconX,