mirror of
https://github.com/go-gitea/gitea.git
synced 2025-02-20 11:43:57 +08:00
Merge branch 'main' into zzc/dev/incoming_mail_new_issue
This commit is contained in:
commit
e4cd1ebbdd
115
.eslintrc.cjs
115
.eslintrc.cjs
@ -1,3 +1,4 @@
|
||||
const vitestPlugin = require('@vitest/eslint-plugin');
|
||||
const restrictedSyntax = ['WithStatement', 'ForInStatement', 'LabeledStatement', 'SequenceExpression'];
|
||||
|
||||
module.exports = {
|
||||
@ -37,8 +38,6 @@ module.exports = {
|
||||
'eslint-plugin-regexp',
|
||||
'eslint-plugin-sonarjs',
|
||||
'eslint-plugin-unicorn',
|
||||
'eslint-plugin-vitest',
|
||||
'eslint-plugin-vitest-globals',
|
||||
'eslint-plugin-wc',
|
||||
],
|
||||
env: {
|
||||
@ -46,6 +45,13 @@ module.exports = {
|
||||
node: true,
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/*.cjs'],
|
||||
rules: {
|
||||
'import-x/no-commonjs': [0],
|
||||
'@typescript-eslint/no-require-imports': [0],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['web_src/**/*'],
|
||||
globals: {
|
||||
@ -82,59 +88,58 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
files: ['**/*.test.*', 'web_src/js/test/setup.ts'],
|
||||
env: {
|
||||
'vitest-globals/env': true,
|
||||
},
|
||||
plugins: ['@vitest/eslint-plugin'],
|
||||
globals: vitestPlugin.environments.env.globals,
|
||||
rules: {
|
||||
'vitest/consistent-test-filename': [0],
|
||||
'vitest/consistent-test-it': [0],
|
||||
'vitest/expect-expect': [0],
|
||||
'vitest/max-expects': [0],
|
||||
'vitest/max-nested-describe': [0],
|
||||
'vitest/no-alias-methods': [0],
|
||||
'vitest/no-commented-out-tests': [0],
|
||||
'vitest/no-conditional-expect': [0],
|
||||
'vitest/no-conditional-in-test': [0],
|
||||
'vitest/no-conditional-tests': [0],
|
||||
'vitest/no-disabled-tests': [0],
|
||||
'vitest/no-done-callback': [0],
|
||||
'vitest/no-duplicate-hooks': [0],
|
||||
'vitest/no-focused-tests': [0],
|
||||
'vitest/no-hooks': [0],
|
||||
'vitest/no-identical-title': [2],
|
||||
'vitest/no-interpolation-in-snapshots': [0],
|
||||
'vitest/no-large-snapshots': [0],
|
||||
'vitest/no-mocks-import': [0],
|
||||
'vitest/no-restricted-matchers': [0],
|
||||
'vitest/no-restricted-vi-methods': [0],
|
||||
'vitest/no-standalone-expect': [0],
|
||||
'vitest/no-test-prefixes': [0],
|
||||
'vitest/no-test-return-statement': [0],
|
||||
'vitest/prefer-called-with': [0],
|
||||
'vitest/prefer-comparison-matcher': [0],
|
||||
'vitest/prefer-each': [0],
|
||||
'vitest/prefer-equality-matcher': [0],
|
||||
'vitest/prefer-expect-resolves': [0],
|
||||
'vitest/prefer-hooks-in-order': [0],
|
||||
'vitest/prefer-hooks-on-top': [2],
|
||||
'vitest/prefer-lowercase-title': [0],
|
||||
'vitest/prefer-mock-promise-shorthand': [0],
|
||||
'vitest/prefer-snapshot-hint': [0],
|
||||
'vitest/prefer-spy-on': [0],
|
||||
'vitest/prefer-strict-equal': [0],
|
||||
'vitest/prefer-to-be': [0],
|
||||
'vitest/prefer-to-be-falsy': [0],
|
||||
'vitest/prefer-to-be-object': [0],
|
||||
'vitest/prefer-to-be-truthy': [0],
|
||||
'vitest/prefer-to-contain': [0],
|
||||
'vitest/prefer-to-have-length': [0],
|
||||
'vitest/prefer-todo': [0],
|
||||
'vitest/require-hook': [0],
|
||||
'vitest/require-to-throw-message': [0],
|
||||
'vitest/require-top-level-describe': [0],
|
||||
'vitest/valid-describe-callback': [2],
|
||||
'vitest/valid-expect': [2],
|
||||
'vitest/valid-title': [2],
|
||||
'@vitest/consistent-test-filename': [0],
|
||||
'@vitest/consistent-test-it': [0],
|
||||
'@vitest/expect-expect': [0],
|
||||
'@vitest/max-expects': [0],
|
||||
'@vitest/max-nested-describe': [0],
|
||||
'@vitest/no-alias-methods': [0],
|
||||
'@vitest/no-commented-out-tests': [0],
|
||||
'@vitest/no-conditional-expect': [0],
|
||||
'@vitest/no-conditional-in-test': [0],
|
||||
'@vitest/no-conditional-tests': [0],
|
||||
'@vitest/no-disabled-tests': [0],
|
||||
'@vitest/no-done-callback': [0],
|
||||
'@vitest/no-duplicate-hooks': [0],
|
||||
'@vitest/no-focused-tests': [0],
|
||||
'@vitest/no-hooks': [0],
|
||||
'@vitest/no-identical-title': [2],
|
||||
'@vitest/no-interpolation-in-snapshots': [0],
|
||||
'@vitest/no-large-snapshots': [0],
|
||||
'@vitest/no-mocks-import': [0],
|
||||
'@vitest/no-restricted-matchers': [0],
|
||||
'@vitest/no-restricted-vi-methods': [0],
|
||||
'@vitest/no-standalone-expect': [0],
|
||||
'@vitest/no-test-prefixes': [0],
|
||||
'@vitest/no-test-return-statement': [0],
|
||||
'@vitest/prefer-called-with': [0],
|
||||
'@vitest/prefer-comparison-matcher': [0],
|
||||
'@vitest/prefer-each': [0],
|
||||
'@vitest/prefer-equality-matcher': [0],
|
||||
'@vitest/prefer-expect-resolves': [0],
|
||||
'@vitest/prefer-hooks-in-order': [0],
|
||||
'@vitest/prefer-hooks-on-top': [2],
|
||||
'@vitest/prefer-lowercase-title': [0],
|
||||
'@vitest/prefer-mock-promise-shorthand': [0],
|
||||
'@vitest/prefer-snapshot-hint': [0],
|
||||
'@vitest/prefer-spy-on': [0],
|
||||
'@vitest/prefer-strict-equal': [0],
|
||||
'@vitest/prefer-to-be': [0],
|
||||
'@vitest/prefer-to-be-falsy': [0],
|
||||
'@vitest/prefer-to-be-object': [0],
|
||||
'@vitest/prefer-to-be-truthy': [0],
|
||||
'@vitest/prefer-to-contain': [0],
|
||||
'@vitest/prefer-to-have-length': [0],
|
||||
'@vitest/prefer-todo': [0],
|
||||
'@vitest/require-hook': [0],
|
||||
'@vitest/require-to-throw-message': [0],
|
||||
'@vitest/require-top-level-describe': [0],
|
||||
'@vitest/valid-describe-callback': [2],
|
||||
'@vitest/valid-expect': [2],
|
||||
'@vitest/valid-title': [2],
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -163,7 +168,7 @@ module.exports = {
|
||||
{
|
||||
files: ['tests/e2e/**'],
|
||||
plugins: [
|
||||
'eslint-plugin-playwright'
|
||||
'eslint-plugin-playwright',
|
||||
],
|
||||
extends: [
|
||||
'plugin:playwright/recommended',
|
||||
|
2
Makefile
2
Makefile
@ -144,7 +144,7 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMAN
|
||||
GO_DIRS := build cmd models modules routers services tests
|
||||
WEB_DIRS := web_src/js web_src/css
|
||||
|
||||
ESLINT_FILES := web_src/js tools *.js *.ts tests/e2e
|
||||
ESLINT_FILES := web_src/js tools *.js *.ts *.cjs tests/e2e
|
||||
STYLELINT_FILES := web_src/css web_src/js/components/*.vue
|
||||
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US.ini .github $(filter-out CHANGELOG.md, $(wildcard *.go *.js *.md *.yml *.yaml *.toml))
|
||||
EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini
|
||||
|
@ -114,6 +114,12 @@ type FindArtifactsOptions struct {
|
||||
Status int
|
||||
}
|
||||
|
||||
func (opts FindArtifactsOptions) ToOrders() string {
|
||||
return "id"
|
||||
}
|
||||
|
||||
var _ db.FindOptionsOrder = (*FindArtifactsOptions)(nil)
|
||||
|
||||
func (opts FindArtifactsOptions) ToConds() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if opts.RepoID > 0 {
|
||||
@ -132,7 +138,7 @@ func (opts FindArtifactsOptions) ToConds() builder.Cond {
|
||||
return cond
|
||||
}
|
||||
|
||||
// ActionArtifactMeta is the meta data of an artifact
|
||||
// ActionArtifactMeta is the meta-data of an artifact
|
||||
type ActionArtifactMeta struct {
|
||||
ArtifactName string
|
||||
FileSize int64
|
||||
|
@ -71,3 +71,10 @@ func KeysOfMap[K comparable, V any](m map[K]V) []K {
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func SliceNilAsEmpty[T any](a []T) []T {
|
||||
if a == nil {
|
||||
return []T{}
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
@ -385,6 +385,12 @@ show_only_public=Apresentando somente os públicos
|
||||
|
||||
issues.in_your_repos=Nos seus repositórios
|
||||
|
||||
guide_title=Sem trabalho
|
||||
guide_desc=Neste momento não está a seguir repositórios nem utilizadores, por isso não há conteúdo a apresentar. Pode explorar repositórios ou utilizadores de interesse a partir das ligações abaixo.
|
||||
explore_repos=Explorar repositórios
|
||||
explore_users=Explorar utilizadores
|
||||
empty_org=Ainda não há organizações.
|
||||
empty_repo=Ainda não há repositórios.
|
||||
|
||||
[explore]
|
||||
repos=Repositórios
|
||||
|
200
package-lock.json
generated
200
package-lock.json
generated
@ -83,6 +83,7 @@
|
||||
"@typescript-eslint/eslint-plugin": "8.21.0",
|
||||
"@typescript-eslint/parser": "8.21.0",
|
||||
"@vitejs/plugin-vue": "5.2.1",
|
||||
"@vitest/eslint-plugin": "1.1.30",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-import-resolver-typescript": "3.7.0",
|
||||
"eslint-plugin-array-func": "4.0.0",
|
||||
@ -94,8 +95,6 @@
|
||||
"eslint-plugin-regexp": "2.7.0",
|
||||
"eslint-plugin-sonarjs": "3.0.1",
|
||||
"eslint-plugin-unicorn": "56.0.1",
|
||||
"eslint-plugin-vitest": "0.4.1",
|
||||
"eslint-plugin-vitest-globals": "1.5.0",
|
||||
"eslint-plugin-vue": "9.32.0",
|
||||
"eslint-plugin-vue-scoped-css": "2.9.0",
|
||||
"eslint-plugin-wc": "2.2.0",
|
||||
@ -5054,6 +5053,27 @@
|
||||
"vue": "^3.2.25"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/eslint-plugin": {
|
||||
"version": "1.1.30",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.1.30.tgz",
|
||||
"integrity": "sha512-gka7VmgfDXmVagcs/SV5Ft23LLrqSzvjX8ATZMLTXIswVRx+i1XfIgy+w2WDrLvhio/eyR6EEb1qM0+hmlF00w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/utils": ">= 8.0",
|
||||
"eslint": ">= 8.57.0",
|
||||
"typescript": ">= 5.0.0",
|
||||
"vitest": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
},
|
||||
"vitest": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/expect": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.3.tgz",
|
||||
@ -8455,182 +8475,6 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vitest/-/eslint-plugin-vitest-0.4.1.tgz",
|
||||
"integrity": "sha512-+PnZ2u/BS+f5FiuHXz4zKsHPcMKHie+K+1Uvu/x91ovkCMEOJqEI8E9Tw1Wzx2QRz4MHOBHYf1ypO8N1K0aNAA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/utils": "^7.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.0.0 || >= 20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=8.0.0",
|
||||
"vitest": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"optional": true
|
||||
},
|
||||
"vitest": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest-globals": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vitest-globals/-/eslint-plugin-vitest-globals-1.5.0.tgz",
|
||||
"integrity": "sha512-ZSsVOaOIig0oVLzRTyk8lUfBfqzWxr/J3/NFMfGGRIkGQPejJYmDH3gXmSJxAojts77uzAGB/UmVrwi2DC4LYA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz",
|
||||
"integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.18.0",
|
||||
"@typescript-eslint/visitor-keys": "7.18.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/types": {
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz",
|
||||
"integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz",
|
||||
"integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.18.0",
|
||||
"@typescript-eslint/visitor-keys": "7.18.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"minimatch": "^9.0.4",
|
||||
"semver": "^7.6.0",
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/utils": {
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz",
|
||||
"integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@typescript-eslint/scope-manager": "7.18.0",
|
||||
"@typescript-eslint/types": "7.18.0",
|
||||
"@typescript-eslint/typescript-estree": "7.18.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.56.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest/node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "7.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz",
|
||||
"integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.18.0",
|
||||
"eslint-visitor-keys": "^3.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest/node_modules/eslint-visitor-keys": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
|
||||
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest/node_modules/minimatch": {
|
||||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vitest/node_modules/ts-api-utils": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
|
||||
"integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-vue": {
|
||||
"version": "9.32.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.32.0.tgz",
|
||||
|
@ -82,6 +82,7 @@
|
||||
"@typescript-eslint/eslint-plugin": "8.21.0",
|
||||
"@typescript-eslint/parser": "8.21.0",
|
||||
"@vitejs/plugin-vue": "5.2.1",
|
||||
"@vitest/eslint-plugin": "1.1.30",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-import-resolver-typescript": "3.7.0",
|
||||
"eslint-plugin-array-func": "4.0.0",
|
||||
@ -93,8 +94,6 @@
|
||||
"eslint-plugin-regexp": "2.7.0",
|
||||
"eslint-plugin-sonarjs": "3.0.1",
|
||||
"eslint-plugin-unicorn": "56.0.1",
|
||||
"eslint-plugin-vitest": "0.4.1",
|
||||
"eslint-plugin-vitest-globals": "1.5.0",
|
||||
"eslint-plugin-vue": "9.32.0",
|
||||
"eslint-plugin-vue-scoped-css": "2.9.0",
|
||||
"eslint-plugin-wc": "2.2.0",
|
||||
|
@ -25,7 +25,7 @@ func PrepareCodeSearch(ctx *context.Context) (ret struct {
|
||||
}
|
||||
isFuzzy := ctx.FormOptionalBool("fuzzy").ValueOrDefault(fuzzyDefault)
|
||||
if isFuzzy && !fuzzyAllow {
|
||||
ctx.Flash.Info("Fuzzy search is disabled by default due to performance reasons")
|
||||
ctx.Flash.Info("Fuzzy search is disabled by default due to performance reasons", true)
|
||||
isFuzzy = false
|
||||
}
|
||||
|
||||
|
@ -276,13 +276,16 @@ func ValidateRepoMetasForNewIssue(ctx *context.Context, form forms.CreateIssueFo
|
||||
}
|
||||
pageMetaData.ProjectsData.SelectedProjectID = form.ProjectID
|
||||
|
||||
// prepare assignees
|
||||
candidateAssignees := toSet(pageMetaData.AssigneesData.CandidateAssignees, func(user *user_model.User) int64 { return user.ID })
|
||||
inputAssigneeIDs, _ := base.StringsToInt64s(strings.Split(form.AssigneeIDs, ","))
|
||||
if len(inputAssigneeIDs) > 0 && !candidateAssignees.Contains(inputAssigneeIDs...) {
|
||||
ctx.NotFound("", nil)
|
||||
return ret
|
||||
var assigneeIDStrings []string
|
||||
for _, inputAssigneeID := range inputAssigneeIDs {
|
||||
if candidateAssignees.Contains(inputAssigneeID) {
|
||||
assigneeIDStrings = append(assigneeIDStrings, strconv.FormatInt(inputAssigneeID, 10))
|
||||
}
|
||||
}
|
||||
pageMetaData.AssigneesData.SelectedAssigneeIDs = form.AssigneeIDs
|
||||
pageMetaData.AssigneesData.SelectedAssigneeIDs = strings.Join(assigneeIDStrings, ",")
|
||||
|
||||
// Check if the passed reviewers (user/team) actually exist
|
||||
var reviewers []*user_model.User
|
||||
|
@ -67,7 +67,7 @@ func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Iss
|
||||
if err := issue.LoadLabels(ctx); err != nil {
|
||||
return &api.Issue{}
|
||||
}
|
||||
apiIssue.Labels = ToLabelList(issue.Labels, issue.Repo, issue.Repo.Owner)
|
||||
apiIssue.Labels = util.SliceNilAsEmpty(ToLabelList(issue.Labels, issue.Repo, issue.Repo.Owner))
|
||||
apiIssue.Repo = &api.RepositoryMeta{
|
||||
ID: issue.Repo.ID,
|
||||
Name: issue.Repo.Name,
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// ToAPIPullRequest assumes following fields have been assigned with valid values:
|
||||
@ -77,7 +78,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u
|
||||
Labels: apiIssue.Labels,
|
||||
Milestone: apiIssue.Milestone,
|
||||
Assignee: apiIssue.Assignee,
|
||||
Assignees: apiIssue.Assignees,
|
||||
Assignees: util.SliceNilAsEmpty(apiIssue.Assignees),
|
||||
State: apiIssue.State,
|
||||
Draft: pr.IsWorkInProgress(ctx),
|
||||
IsLocked: apiIssue.IsLocked,
|
||||
@ -94,6 +95,10 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u
|
||||
Updated: pr.Issue.UpdatedUnix.AsTimePtr(),
|
||||
PinOrder: apiIssue.PinOrder,
|
||||
|
||||
// output "[]" rather than null to align to github outputs
|
||||
RequestedReviewers: []*api.User{},
|
||||
RequestedReviewersTeams: []*api.Team{},
|
||||
|
||||
AllowMaintainerEdit: pr.AllowMaintainerEdit,
|
||||
|
||||
Base: &api.PRBranchInfo{
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
unit_model "code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// ToRepo converts a Repository to api.Repository
|
||||
@ -242,7 +243,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
||||
MirrorInterval: mirrorInterval,
|
||||
MirrorUpdated: mirrorUpdated,
|
||||
RepoTransfer: transfer,
|
||||
Topics: repo.Topics,
|
||||
Topics: util.SliceNilAsEmpty(repo.Topics),
|
||||
ObjectFormatName: repo.ObjectFormatName,
|
||||
Licenses: repoLicenses.StringList(),
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/proxy"
|
||||
"code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
@ -161,11 +162,13 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error {
|
||||
|
||||
log.Trace("Pushing %s mirror[%d] remote %s", path, m.ID, m.RemoteName)
|
||||
|
||||
envs := proxy.EnvWithProxy(remoteURL.URL)
|
||||
if err := git.Push(ctx, path, git.PushOptions{
|
||||
Remote: m.RemoteName,
|
||||
Force: true,
|
||||
Mirror: true,
|
||||
Timeout: timeout,
|
||||
Env: envs,
|
||||
}); err != nil {
|
||||
log.Error("Error pushing %s mirror[%d] remote %s: %v", path, m.ID, m.RemoteName, err)
|
||||
|
||||
|
@ -235,6 +235,28 @@ func buildPackagesIndex(ctx context.Context, ownerID int64, repoVersion *package
|
||||
return packages_service.DeletePackageFile(ctx, pf)
|
||||
}
|
||||
|
||||
vpfs := make(map[int64]*entryOptions)
|
||||
for _, pf := range pfs {
|
||||
current := &entryOptions{
|
||||
File: pf,
|
||||
}
|
||||
current.Version, err = packages_model.GetVersionByID(ctx, pf.VersionID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// here we compare the versions but not using SearchLatestVersions because we shouldn't allow "downgrading" to a older version by "latest" one.
|
||||
// https://wiki.archlinux.org/title/Downgrading_packages : randomly downgrading can mess up dependencies:
|
||||
// If a downgrade involves a soname change, all dependencies may need downgrading or rebuilding too.
|
||||
if old, ok := vpfs[current.Version.PackageID]; ok {
|
||||
if compareVersions(old.Version.Version, current.Version.Version) == -1 {
|
||||
vpfs[current.Version.PackageID] = current
|
||||
}
|
||||
} else {
|
||||
vpfs[current.Version.PackageID] = current
|
||||
}
|
||||
}
|
||||
|
||||
indexContent, _ := packages_module.NewHashedBuffer()
|
||||
defer indexContent.Close()
|
||||
|
||||
@ -243,15 +265,7 @@ func buildPackagesIndex(ctx context.Context, ownerID int64, repoVersion *package
|
||||
|
||||
cache := make(map[int64]*packages_model.Package)
|
||||
|
||||
for _, pf := range pfs {
|
||||
opts := &entryOptions{
|
||||
File: pf,
|
||||
}
|
||||
|
||||
opts.Version, err = packages_model.GetVersionByID(ctx, pf.VersionID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, opts := range vpfs {
|
||||
if err := json.Unmarshal([]byte(opts.Version.MetadataJSON), &opts.VersionMetadata); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -263,12 +277,12 @@ func buildPackagesIndex(ctx context.Context, ownerID int64, repoVersion *package
|
||||
}
|
||||
cache[opts.Package.ID] = opts.Package
|
||||
}
|
||||
opts.Blob, err = packages_model.GetBlobByID(ctx, pf.BlobID)
|
||||
opts.Blob, err = packages_model.GetBlobByID(ctx, opts.File.BlobID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sig, err := packages_model.GetPropertiesByName(ctx, packages_model.PropertyTypeFile, pf.ID, arch_module.PropertySignature)
|
||||
sig, err := packages_model.GetPropertiesByName(ctx, packages_model.PropertyTypeFile, opts.File.ID, arch_module.PropertySignature)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -277,7 +291,7 @@ func buildPackagesIndex(ctx context.Context, ownerID int64, repoVersion *package
|
||||
}
|
||||
opts.Signature = sig[0].Value
|
||||
|
||||
meta, err := packages_model.GetPropertiesByName(ctx, packages_model.PropertyTypeFile, pf.ID, arch_module.PropertyMetadata)
|
||||
meta, err := packages_model.GetPropertiesByName(ctx, packages_model.PropertyTypeFile, opts.File.ID, arch_module.PropertyMetadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
113
services/packages/arch/vercmp.go
Normal file
113
services/packages/arch/vercmp.go
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package arch
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// https://gitlab.archlinux.org/pacman/pacman/-/blob/d55b47e5512808b67bc944feb20c2bcc6c1a4c45/lib/libalpm/version.c
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func parseEVR(evr string) (epoch, version, release string) {
|
||||
if before, after, f := strings.Cut(evr, ":"); f {
|
||||
epoch = before
|
||||
evr = after
|
||||
} else {
|
||||
epoch = "0"
|
||||
}
|
||||
|
||||
if before, after, f := strings.Cut(evr, "-"); f {
|
||||
version = before
|
||||
release = after
|
||||
} else {
|
||||
version = evr
|
||||
release = "1"
|
||||
}
|
||||
return epoch, version, release
|
||||
}
|
||||
|
||||
func compareSegments(a, b []string) int {
|
||||
lenA, lenB := len(a), len(b)
|
||||
var l int
|
||||
if lenA > lenB {
|
||||
l = lenB
|
||||
} else {
|
||||
l = lenA
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
if r := compare(a[i], b[i]); r != 0 {
|
||||
return r
|
||||
}
|
||||
}
|
||||
if lenA == lenB {
|
||||
return 0
|
||||
} else if l == lenA {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func compare(a, b string) int {
|
||||
if a == b {
|
||||
return 0
|
||||
}
|
||||
|
||||
aNumeric := isNumeric(a)
|
||||
bNumeric := isNumeric(b)
|
||||
|
||||
if aNumeric && bNumeric {
|
||||
aInt, _ := strconv.Atoi(a)
|
||||
bInt, _ := strconv.Atoi(b)
|
||||
switch {
|
||||
case aInt < bInt:
|
||||
return -1
|
||||
case aInt > bInt:
|
||||
return 1
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
if aNumeric {
|
||||
return 1
|
||||
}
|
||||
if bNumeric {
|
||||
return -1
|
||||
}
|
||||
|
||||
return strings.Compare(a, b)
|
||||
}
|
||||
|
||||
func isNumeric(s string) bool {
|
||||
for _, c := range s {
|
||||
if !unicode.IsDigit(c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func compareVersions(a, b string) int {
|
||||
if a == b {
|
||||
return 0
|
||||
}
|
||||
|
||||
epochA, versionA, releaseA := parseEVR(a)
|
||||
epochB, versionB, releaseB := parseEVR(b)
|
||||
|
||||
if res := compareSegments([]string{epochA}, []string{epochB}); res != 0 {
|
||||
return res
|
||||
}
|
||||
|
||||
if res := compareSegments(strings.Split(versionA, "."), strings.Split(versionB, ".")); res != 0 {
|
||||
return res
|
||||
}
|
||||
|
||||
return compareSegments([]string{releaseA}, []string{releaseB})
|
||||
}
|
27
services/packages/arch/vercmp_test.go
Normal file
27
services/packages/arch/vercmp_test.go
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package arch
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCompareVersions(t *testing.T) {
|
||||
// https://man.archlinux.org/man/vercmp.8.en
|
||||
checks := [][]string{
|
||||
{"1.0a", "1.0b", "1.0beta", "1.0p", "1.0pre", "1.0rc", "1.0", "1.0.a", "1.0.1"},
|
||||
{"1", "1.0", "1.1", "1.1.1", "1.2", "2.0", "3.0.0"},
|
||||
}
|
||||
for _, check := range checks {
|
||||
for i := 0; i < len(check)-1; i++ {
|
||||
require.Equal(t, -1, compareVersions(check[i], check[i+1]))
|
||||
require.Equal(t, 1, compareVersions(check[i+1], check[i]))
|
||||
}
|
||||
}
|
||||
require.Equal(t, 1, compareVersions("1.0-2", "1.0"))
|
||||
require.Equal(t, 0, compareVersions("0:1.0-1", "1.0"))
|
||||
require.Equal(t, 1, compareVersions("1:1.0-1", "2.0"))
|
||||
}
|
@ -52,8 +52,9 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR
|
||||
IsEmpty: !opts.AutoInit,
|
||||
}
|
||||
|
||||
repoPath := repo_model.RepoPath(u.Name, repo.Name)
|
||||
|
||||
if err := db.WithTx(ctx, func(ctx context.Context) error {
|
||||
repoPath := repo_model.RepoPath(u.Name, repo.Name)
|
||||
isExist, err := util.IsExist(repoPath)
|
||||
if err != nil {
|
||||
log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
|
||||
@ -75,7 +76,12 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR
|
||||
if repo, err = repo_model.GetRepositoryByID(ctx, repo.ID); err != nil {
|
||||
return fmt.Errorf("getRepositoryByID: %w", err)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := func() error {
|
||||
if err := adoptRepository(ctx, repoPath, repo, opts.DefaultBranch); err != nil {
|
||||
return fmt.Errorf("adoptRepository: %w", err)
|
||||
}
|
||||
@ -84,23 +90,18 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts CreateR
|
||||
return fmt.Errorf("checkDaemonExportOK: %w", err)
|
||||
}
|
||||
|
||||
// Initialize Issue Labels if selected
|
||||
if len(opts.IssueLabels) > 0 {
|
||||
if err := repo_module.InitializeLabels(ctx, repo.ID, opts.IssueLabels, false); err != nil {
|
||||
return fmt.Errorf("InitializeLabels: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if stdout, _, err := git.NewCommand(ctx, "update-server-info").
|
||||
RunStdString(&git.RunOpts{Dir: repoPath}); err != nil {
|
||||
log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err)
|
||||
return fmt.Errorf("CreateRepository(git update-server-info): %w", err)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
}(); err != nil {
|
||||
if errDel := DeleteRepository(ctx, doer, repo, false /* no notify */); errDel != nil {
|
||||
log.Error("Failed to delete repository %s that could not be adopted: %v", repo.FullName(), errDel)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
notify_service.AdoptRepository(ctx, doer, u, repo)
|
||||
|
||||
return repo, nil
|
||||
|
@ -79,6 +79,34 @@ license = MIT`)
|
||||
|
||||
return buf.Bytes()
|
||||
}
|
||||
readIndexContent := func(r io.Reader) (map[string]string, error) {
|
||||
gzr, err := gzip.NewReader(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
content := make(map[string]string)
|
||||
|
||||
tr := tar.NewReader(gzr)
|
||||
for {
|
||||
hd, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(tr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
content[hd.Name] = string(buf)
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
||||
compressions := []string{"gz", "xz", "zst"}
|
||||
repositories := []string{"main", "testing", "with/slash", ""}
|
||||
@ -171,35 +199,6 @@ license = MIT`)
|
||||
MakeRequest(t, req, http.StatusConflict)
|
||||
})
|
||||
|
||||
readIndexContent := func(r io.Reader) (map[string]string, error) {
|
||||
gzr, err := gzip.NewReader(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
content := make(map[string]string)
|
||||
|
||||
tr := tar.NewReader(gzr)
|
||||
for {
|
||||
hd, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf, err := io.ReadAll(tr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
content[hd.Name] = string(buf)
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
||||
t.Run("Index", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
@ -299,4 +298,39 @@ license = MIT`)
|
||||
})
|
||||
}
|
||||
}
|
||||
t.Run("KeepLastVersion", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
pkgVer1 := createPackage("gz", "gitea-test", "1.0.0", "aarch64")
|
||||
pkgVer2 := createPackage("gz", "gitea-test", "1.0.1", "aarch64")
|
||||
req := NewRequestWithBody(t, "PUT", rootURL, bytes.NewReader(pkgVer1)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusCreated)
|
||||
req = NewRequestWithBody(t, "PUT", rootURL, bytes.NewReader(pkgVer2)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("%s/aarch64/%s", rootURL, arch_service.IndexArchiveFilename))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
content, err := readIndexContent(resp.Body)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, content, 2)
|
||||
|
||||
_, has := content["gitea-test-1.0.0/desc"]
|
||||
assert.False(t, has)
|
||||
_, has = content["gitea-test-1.0.1/desc"]
|
||||
assert.True(t, has)
|
||||
|
||||
req = NewRequest(t, "DELETE", fmt.Sprintf("%s/gitea-test/1.0.1/aarch64", rootURL)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("%s/aarch64/%s", rootURL, arch_service.IndexArchiveFilename))
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
content, err = readIndexContent(resp.Body)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, content, 2)
|
||||
_, has = content["gitea-test-1.0.0/desc"]
|
||||
assert.True(t, has)
|
||||
})
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
{
|
||||
"include": [
|
||||
"*",
|
||||
"tests/e2e/**/*",
|
||||
"tools/**/*",
|
||||
"web_src/js/**/*",
|
||||
"${configDir}/.*",
|
||||
"${configDir}/*",
|
||||
"${configDir}/tests/e2e/**/*",
|
||||
"${configDir}/tests/e2e/**/.*",
|
||||
"${configDir}/tools/**/*",
|
||||
"${configDir}/tools/**/.*",
|
||||
"${configDir}/web_src/js/**/*",
|
||||
"${configDir}/web_src/js/**/.*",
|
||||
],
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
|
Loading…
x
Reference in New Issue
Block a user