mirror of
https://github.com/go-gitea/gitea
synced 2025-01-25 09:04:29 +00:00
Merge branch 'main' into lunny/refactor_getpatch
This commit is contained in:
commit
a2804a5efc
100
.eslintrc.yaml
100
.eslintrc.yaml
@ -16,10 +16,10 @@ parserOptions:
|
|||||||
parser: "@typescript-eslint/parser" # for vue plugin - https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
|
parser: "@typescript-eslint/parser" # for vue plugin - https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
import/extensions: [".js", ".ts"]
|
import-x/extensions: [".js", ".ts"]
|
||||||
import/parsers:
|
import-x/parsers:
|
||||||
"@typescript-eslint/parser": [".js", ".ts"]
|
"@typescript-eslint/parser": [".js", ".ts"]
|
||||||
import/resolver:
|
import-x/resolver:
|
||||||
typescript: true
|
typescript: true
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
@ -28,7 +28,7 @@ plugins:
|
|||||||
- "@typescript-eslint/eslint-plugin"
|
- "@typescript-eslint/eslint-plugin"
|
||||||
- eslint-plugin-array-func
|
- eslint-plugin-array-func
|
||||||
- eslint-plugin-github
|
- eslint-plugin-github
|
||||||
- eslint-plugin-i
|
- eslint-plugin-import-x
|
||||||
- eslint-plugin-no-jquery
|
- eslint-plugin-no-jquery
|
||||||
- eslint-plugin-no-use-extend-native
|
- eslint-plugin-no-use-extend-native
|
||||||
- eslint-plugin-regexp
|
- eslint-plugin-regexp
|
||||||
@ -58,15 +58,15 @@ overrides:
|
|||||||
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, status, statusbar, stop, toolbar, top]
|
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, status, statusbar, stop, toolbar, top]
|
||||||
- files: ["*.config.*"]
|
- files: ["*.config.*"]
|
||||||
rules:
|
rules:
|
||||||
i/no-unused-modules: [0]
|
import-x/no-unused-modules: [0]
|
||||||
- files: ["**/*.d.ts"]
|
- files: ["**/*.d.ts"]
|
||||||
rules:
|
rules:
|
||||||
i/no-unused-modules: [0]
|
import-x/no-unused-modules: [0]
|
||||||
"@typescript-eslint/consistent-type-definitions": [0]
|
"@typescript-eslint/consistent-type-definitions": [0]
|
||||||
"@typescript-eslint/consistent-type-imports": [0]
|
"@typescript-eslint/consistent-type-imports": [0]
|
||||||
- files: ["web_src/js/types.ts"]
|
- files: ["web_src/js/types.ts"]
|
||||||
rules:
|
rules:
|
||||||
i/no-unused-modules: [0]
|
import-x/no-unused-modules: [0]
|
||||||
- files: ["**/*.test.*", "web_src/js/test/setup.ts"]
|
- files: ["**/*.test.*", "web_src/js/test/setup.ts"]
|
||||||
env:
|
env:
|
||||||
vitest-globals/env: true
|
vitest-globals/env: true
|
||||||
@ -394,49 +394,49 @@ rules:
|
|||||||
id-blacklist: [0]
|
id-blacklist: [0]
|
||||||
id-length: [0]
|
id-length: [0]
|
||||||
id-match: [0]
|
id-match: [0]
|
||||||
i/consistent-type-specifier-style: [0]
|
import-x/consistent-type-specifier-style: [0]
|
||||||
i/default: [0]
|
import-x/default: [0]
|
||||||
i/dynamic-import-chunkname: [0]
|
import-x/dynamic-import-chunkname: [0]
|
||||||
i/export: [2]
|
import-x/export: [2]
|
||||||
i/exports-last: [0]
|
import-x/exports-last: [0]
|
||||||
i/extensions: [2, always, {ignorePackages: true}]
|
import-x/extensions: [2, always, {ignorePackages: true}]
|
||||||
i/first: [2]
|
import-x/first: [2]
|
||||||
i/group-exports: [0]
|
import-x/group-exports: [0]
|
||||||
i/max-dependencies: [0]
|
import-x/max-dependencies: [0]
|
||||||
i/named: [2]
|
import-x/named: [2]
|
||||||
i/namespace: [0]
|
import-x/namespace: [0]
|
||||||
i/newline-after-import: [0]
|
import-x/newline-after-import: [0]
|
||||||
i/no-absolute-path: [0]
|
import-x/no-absolute-path: [0]
|
||||||
i/no-amd: [2]
|
import-x/no-amd: [2]
|
||||||
i/no-anonymous-default-export: [0]
|
import-x/no-anonymous-default-export: [0]
|
||||||
i/no-commonjs: [2]
|
import-x/no-commonjs: [2]
|
||||||
i/no-cycle: [2, {ignoreExternal: true, maxDepth: 1}]
|
import-x/no-cycle: [2, {ignoreExternal: true, maxDepth: 1}]
|
||||||
i/no-default-export: [0]
|
import-x/no-default-export: [0]
|
||||||
i/no-deprecated: [0]
|
import-x/no-deprecated: [0]
|
||||||
i/no-dynamic-require: [0]
|
import-x/no-dynamic-require: [0]
|
||||||
i/no-empty-named-blocks: [2]
|
import-x/no-empty-named-blocks: [2]
|
||||||
i/no-extraneous-dependencies: [2]
|
import-x/no-extraneous-dependencies: [2]
|
||||||
i/no-import-module-exports: [0]
|
import-x/no-import-module-exports: [0]
|
||||||
i/no-internal-modules: [0]
|
import-x/no-internal-modules: [0]
|
||||||
i/no-mutable-exports: [0]
|
import-x/no-mutable-exports: [0]
|
||||||
i/no-named-as-default-member: [0]
|
import-x/no-named-as-default-member: [0]
|
||||||
i/no-named-as-default: [0]
|
import-x/no-named-as-default: [0]
|
||||||
i/no-named-default: [0]
|
import-x/no-named-default: [0]
|
||||||
i/no-named-export: [0]
|
import-x/no-named-export: [0]
|
||||||
i/no-namespace: [0]
|
import-x/no-namespace: [0]
|
||||||
i/no-nodejs-modules: [0]
|
import-x/no-nodejs-modules: [0]
|
||||||
i/no-relative-packages: [0]
|
import-x/no-relative-packages: [0]
|
||||||
i/no-relative-parent-imports: [0]
|
import-x/no-relative-parent-imports: [0]
|
||||||
i/no-restricted-paths: [0]
|
import-x/no-restricted-paths: [0]
|
||||||
i/no-self-import: [2]
|
import-x/no-self-import: [2]
|
||||||
i/no-unassigned-import: [0]
|
import-x/no-unassigned-import: [0]
|
||||||
i/no-unresolved: [2, {commonjs: true, ignore: ["\\?.+$"]}]
|
import-x/no-unresolved: [2, {commonjs: true, ignore: ["\\?.+$"]}]
|
||||||
i/no-unused-modules: [2, {unusedExports: true}]
|
import-x/no-unused-modules: [2, {unusedExports: true}]
|
||||||
i/no-useless-path-segments: [2, {commonjs: true}]
|
import-x/no-useless-path-segments: [2, {commonjs: true}]
|
||||||
i/no-webpack-loader-syntax: [2]
|
import-x/no-webpack-loader-syntax: [2]
|
||||||
i/order: [0]
|
import-x/order: [0]
|
||||||
i/prefer-default-export: [0]
|
import-x/prefer-default-export: [0]
|
||||||
i/unambiguous: [0]
|
import-x/unambiguous: [0]
|
||||||
init-declarations: [0]
|
init-declarations: [0]
|
||||||
line-comment-position: [0]
|
line-comment-position: [0]
|
||||||
logical-assignment-operators: [0]
|
logical-assignment-operators: [0]
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
package db // it's not db_test, because this file is for testing the private type halfCommitter
|
package db // it's not db_test, because this file is for testing the private type halfCommitter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -80,7 +80,7 @@ func Test_halfCommitter(t *testing.T) {
|
|||||||
testWithCommitter(mockCommitter, func(committer Committer) error {
|
testWithCommitter(mockCommitter, func(committer Committer) error {
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
if true {
|
if true {
|
||||||
return fmt.Errorf("error")
|
return errors.New("error")
|
||||||
}
|
}
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
})
|
})
|
||||||
@ -94,7 +94,7 @@ func Test_halfCommitter(t *testing.T) {
|
|||||||
testWithCommitter(mockCommitter, func(committer Committer) error {
|
testWithCommitter(mockCommitter, func(committer Committer) error {
|
||||||
committer.Close()
|
committer.Close()
|
||||||
committer.Commit()
|
committer.Commit()
|
||||||
return fmt.Errorf("error")
|
return errors.New("error")
|
||||||
})
|
})
|
||||||
|
|
||||||
mockCommitter.Assert(t)
|
mockCommitter.Assert(t)
|
||||||
|
@ -474,3 +474,17 @@ func (c *Commit) GetRepositoryDefaultPublicGPGKey(forceUpdate bool) (*GPGSetting
|
|||||||
}
|
}
|
||||||
return c.repo.GetDefaultPublicGPGKey(forceUpdate)
|
return c.repo.GetDefaultPublicGPGKey(forceUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsStringLikelyCommitID(objFmt ObjectFormat, s string, minLength ...int) bool {
|
||||||
|
minLen := util.OptionalArg(minLength, objFmt.FullLength())
|
||||||
|
if len(s) < minLen || len(s) > objFmt.FullLength() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range s {
|
||||||
|
isHex := (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
|
||||||
|
if !isHex {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
@ -142,7 +142,6 @@ func (ref RefName) RemoteName() string {
|
|||||||
|
|
||||||
// ShortName returns the short name of the reference name
|
// ShortName returns the short name of the reference name
|
||||||
func (ref RefName) ShortName() string {
|
func (ref RefName) ShortName() string {
|
||||||
refName := string(ref)
|
|
||||||
if ref.IsBranch() {
|
if ref.IsBranch() {
|
||||||
return ref.BranchName()
|
return ref.BranchName()
|
||||||
}
|
}
|
||||||
@ -158,8 +157,7 @@ func (ref RefName) ShortName() string {
|
|||||||
if ref.IsFor() {
|
if ref.IsFor() {
|
||||||
return ref.ForBranchName()
|
return ref.ForBranchName()
|
||||||
}
|
}
|
||||||
|
return string(ref) // usually it is a commit ID
|
||||||
return refName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefGroup returns the group type of the reference
|
// RefGroup returns the group type of the reference
|
||||||
|
@ -61,3 +61,31 @@ func parseTags(refs []string) []string {
|
|||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnstableGuessRefByShortName does the best guess to see whether a "short name" provided by user is a branch, tag or commit.
|
||||||
|
// It could guess wrongly if the input is already ambiguous. For example:
|
||||||
|
// * "refs/heads/the-name" vs "refs/heads/refs/heads/the-name"
|
||||||
|
// * "refs/tags/1234567890" vs commit "1234567890"
|
||||||
|
// In most cases, it SHOULD AVOID using this function, unless there is an irresistible reason (eg: make API friendly to end users)
|
||||||
|
// If the function is used, the caller SHOULD CHECK the ref type carefully.
|
||||||
|
func (repo *Repository) UnstableGuessRefByShortName(shortName string) RefName {
|
||||||
|
if repo.IsBranchExist(shortName) {
|
||||||
|
return RefNameFromBranch(shortName)
|
||||||
|
}
|
||||||
|
if repo.IsTagExist(shortName) {
|
||||||
|
return RefNameFromTag(shortName)
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(shortName, "refs/") {
|
||||||
|
if repo.IsReferenceExist(shortName) {
|
||||||
|
return RefName(shortName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commit, err := repo.GetCommit(shortName)
|
||||||
|
if err == nil {
|
||||||
|
commitIDString := commit.ID.String()
|
||||||
|
if strings.HasPrefix(commitIDString, shortName) {
|
||||||
|
return RefName(commitIDString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
@ -64,7 +64,7 @@ func TestLockAndDo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testLockAndDo(t *testing.T) {
|
func testLockAndDo(t *testing.T) {
|
||||||
const concurrency = 1000
|
const concurrency = 50
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
count := 0
|
count := 0
|
||||||
|
@ -278,6 +278,16 @@ type CreateBranchRepoOption struct {
|
|||||||
OldRefName string `json:"old_ref_name" binding:"GitRefName;MaxSize(100)"`
|
OldRefName string `json:"old_ref_name" binding:"GitRefName;MaxSize(100)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateBranchRepoOption options when updating a branch in a repository
|
||||||
|
// swagger:model
|
||||||
|
type UpdateBranchRepoOption struct {
|
||||||
|
// New branch name
|
||||||
|
//
|
||||||
|
// required: true
|
||||||
|
// unique: true
|
||||||
|
Name string `json:"name" binding:"Required;GitRefName;MaxSize(100)"`
|
||||||
|
}
|
||||||
|
|
||||||
// TransferRepoOption options when transfer a repository's ownership
|
// TransferRepoOption options when transfer a repository's ownership
|
||||||
// swagger:model
|
// swagger:model
|
||||||
type TransferRepoOption struct {
|
type TransferRepoOption struct {
|
||||||
|
@ -47,7 +47,7 @@ webauthn_error_unknown=Ocorreu um erro desconhecido. Tente novamente, por favor.
|
|||||||
webauthn_error_insecure=`WebAuthn apenas suporta conexões seguras. Para testar sobre HTTP, pode usar a origem "localhost" ou "127.0.0.1"`
|
webauthn_error_insecure=`WebAuthn apenas suporta conexões seguras. Para testar sobre HTTP, pode usar a origem "localhost" ou "127.0.0.1"`
|
||||||
webauthn_error_unable_to_process=O servidor não conseguiu processar o seu pedido.
|
webauthn_error_unable_to_process=O servidor não conseguiu processar o seu pedido.
|
||||||
webauthn_error_duplicated=A chave de segurança não é permitida neste pedido. Certifique-se de que a chave não está já registada.
|
webauthn_error_duplicated=A chave de segurança não é permitida neste pedido. Certifique-se de que a chave não está já registada.
|
||||||
webauthn_error_empty=Você tem que definir um nome para esta chave.
|
webauthn_error_empty=Tem de definir um nome para esta chave.
|
||||||
webauthn_error_timeout=O tempo limite foi atingido antes que a sua chave pudesse ser lida. Recarregue esta página e tente novamente.
|
webauthn_error_timeout=O tempo limite foi atingido antes que a sua chave pudesse ser lida. Recarregue esta página e tente novamente.
|
||||||
webauthn_reload=Recarregar
|
webauthn_reload=Recarregar
|
||||||
|
|
||||||
@ -1109,6 +1109,7 @@ delete_preexisting_success=Eliminados os ficheiros não adoptados em %s
|
|||||||
blame_prior=Ver a responsabilização anterior a esta modificação
|
blame_prior=Ver a responsabilização anterior a esta modificação
|
||||||
blame.ignore_revs=Ignorando as revisões em <a href="%s">.git-blame-ignore-revs</a>. Clique <a href="%s">aqui para contornar</a> e ver a vista normal de responsabilização.
|
blame.ignore_revs=Ignorando as revisões em <a href="%s">.git-blame-ignore-revs</a>. Clique <a href="%s">aqui para contornar</a> e ver a vista normal de responsabilização.
|
||||||
blame.ignore_revs.failed=Falhou ao ignorar as revisões em <a href="%s">.git-blame-ignore-revs</a>.
|
blame.ignore_revs.failed=Falhou ao ignorar as revisões em <a href="%s">.git-blame-ignore-revs</a>.
|
||||||
|
user_search_tooltip=Mostra um máximo de 30 utilizadores
|
||||||
|
|
||||||
tree_path_not_found_commit=A localização %[1]s não existe no cometimento %[2]s
|
tree_path_not_found_commit=A localização %[1]s não existe no cometimento %[2]s
|
||||||
tree_path_not_found_branch=A localização %[1]s não existe no ramo %[2]s
|
tree_path_not_found_branch=A localização %[1]s não existe no ramo %[2]s
|
||||||
@ -1527,6 +1528,8 @@ issues.filter_assignee=Encarregado
|
|||||||
issues.filter_assginee_no_select=Todos os encarregados
|
issues.filter_assginee_no_select=Todos os encarregados
|
||||||
issues.filter_assginee_no_assignee=Sem encarregado
|
issues.filter_assginee_no_assignee=Sem encarregado
|
||||||
issues.filter_poster=Autor(a)
|
issues.filter_poster=Autor(a)
|
||||||
|
issues.filter_user_placeholder=Procurar utilizadores
|
||||||
|
issues.filter_user_no_select=Todos os utilizadores
|
||||||
issues.filter_type=Tipo
|
issues.filter_type=Tipo
|
||||||
issues.filter_type.all_issues=Todas as questões
|
issues.filter_type.all_issues=Todas as questões
|
||||||
issues.filter_type.assigned_to_you=Atribuídas a si
|
issues.filter_type.assigned_to_you=Atribuídas a si
|
||||||
|
94
package-lock.json
generated
94
package-lock.json
generated
@ -87,7 +87,7 @@
|
|||||||
"eslint-import-resolver-typescript": "3.7.0",
|
"eslint-import-resolver-typescript": "3.7.0",
|
||||||
"eslint-plugin-array-func": "4.0.0",
|
"eslint-plugin-array-func": "4.0.0",
|
||||||
"eslint-plugin-github": "5.1.3",
|
"eslint-plugin-github": "5.1.3",
|
||||||
"eslint-plugin-i": "2.29.1",
|
"eslint-plugin-import-x": "4.5.0",
|
||||||
"eslint-plugin-no-jquery": "3.1.0",
|
"eslint-plugin-no-jquery": "3.1.0",
|
||||||
"eslint-plugin-no-use-extend-native": "0.5.0",
|
"eslint-plugin-no-use-extend-native": "0.5.0",
|
||||||
"eslint-plugin-playwright": "2.1.0",
|
"eslint-plugin-playwright": "2.1.0",
|
||||||
@ -8385,56 +8385,6 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-plugin-i": {
|
|
||||||
"version": "2.29.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-i/-/eslint-plugin-i-2.29.1.tgz",
|
|
||||||
"integrity": "sha512-ORizX37MelIWLbMyqI7hi8VJMf7A0CskMmYkB+lkCX3aF4pkGV7kwx5bSEb4qx7Yce2rAf9s34HqDRPjGRZPNQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"debug": "^4.3.4",
|
|
||||||
"doctrine": "^3.0.0",
|
|
||||||
"eslint-import-resolver-node": "^0.3.9",
|
|
||||||
"eslint-module-utils": "^2.8.0",
|
|
||||||
"get-tsconfig": "^4.7.2",
|
|
||||||
"is-glob": "^4.0.3",
|
|
||||||
"minimatch": "^3.1.2",
|
|
||||||
"semver": "^7.5.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://opencollective.com/unts"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"eslint": "^7.2.0 || ^8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eslint-plugin-i/node_modules/brace-expansion": {
|
|
||||||
"version": "1.1.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"balanced-match": "^1.0.0",
|
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eslint-plugin-i/node_modules/minimatch": {
|
|
||||||
"version": "3.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"brace-expansion": "^1.1.7"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/eslint-plugin-i18n-text": {
|
"node_modules/eslint-plugin-i18n-text": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-i18n-text/-/eslint-plugin-i18n-text-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-i18n-text/-/eslint-plugin-i18n-text-1.0.1.tgz",
|
||||||
@ -8479,6 +8429,48 @@
|
|||||||
"eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
|
"eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint-plugin-import-x": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint-plugin-import-x/-/eslint-plugin-import-x-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-l0OTfnPF8RwmSXfjT75N8d6ZYLVrVYWpaGlgvVkVqFERCI5SyBfDP7QEMr3kt0zWi2sOa9EQ47clbdFsHkF83Q==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/scope-manager": "^8.1.0",
|
||||||
|
"@typescript-eslint/utils": "^8.1.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"doctrine": "^3.0.0",
|
||||||
|
"eslint-import-resolver-node": "^0.3.9",
|
||||||
|
"get-tsconfig": "^4.7.3",
|
||||||
|
"is-glob": "^4.0.3",
|
||||||
|
"minimatch": "^9.0.3",
|
||||||
|
"semver": "^7.6.3",
|
||||||
|
"stable-hash": "^0.0.4",
|
||||||
|
"tslib": "^2.6.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"eslint": "^8.57.0 || ^9.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/eslint-plugin-import-x/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-import/node_modules/brace-expansion": {
|
"node_modules/eslint-plugin-import/node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
"eslint-import-resolver-typescript": "3.7.0",
|
"eslint-import-resolver-typescript": "3.7.0",
|
||||||
"eslint-plugin-array-func": "4.0.0",
|
"eslint-plugin-array-func": "4.0.0",
|
||||||
"eslint-plugin-github": "5.1.3",
|
"eslint-plugin-github": "5.1.3",
|
||||||
"eslint-plugin-i": "2.29.1",
|
"eslint-plugin-import-x": "4.5.0",
|
||||||
"eslint-plugin-no-jquery": "3.1.0",
|
"eslint-plugin-no-jquery": "3.1.0",
|
||||||
"eslint-plugin-no-use-extend-native": "0.5.0",
|
"eslint-plugin-no-use-extend-native": "0.5.0",
|
||||||
"eslint-plugin-playwright": "2.1.0",
|
"eslint-plugin-playwright": "2.1.0",
|
||||||
|
@ -1195,6 +1195,7 @@ func Routes() *web.Router {
|
|||||||
m.Get("/*", repo.GetBranch)
|
m.Get("/*", repo.GetBranch)
|
||||||
m.Delete("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, repo.DeleteBranch)
|
m.Delete("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, repo.DeleteBranch)
|
||||||
m.Post("", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
|
m.Post("", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
|
||||||
|
m.Patch("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.UpdateBranchRepoOption{}), repo.UpdateBranch)
|
||||||
}, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode))
|
}, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode))
|
||||||
m.Group("/branch_protections", func() {
|
m.Group("/branch_protections", func() {
|
||||||
m.Get("", repo.ListBranchProtections)
|
m.Get("", repo.ListBranchProtections)
|
||||||
|
@ -386,6 +386,77 @@ func ListBranches(ctx *context.APIContext) {
|
|||||||
ctx.JSON(http.StatusOK, apiBranches)
|
ctx.JSON(http.StatusOK, apiBranches)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateBranch updates a repository's branch.
|
||||||
|
func UpdateBranch(ctx *context.APIContext) {
|
||||||
|
// swagger:operation PATCH /repos/{owner}/{repo}/branches/{branch} repository repoUpdateBranch
|
||||||
|
// ---
|
||||||
|
// summary: Update a branch
|
||||||
|
// consumes:
|
||||||
|
// - application/json
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: owner
|
||||||
|
// in: path
|
||||||
|
// description: owner of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: repo
|
||||||
|
// in: path
|
||||||
|
// description: name of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: branch
|
||||||
|
// in: path
|
||||||
|
// description: name of the branch
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: body
|
||||||
|
// in: body
|
||||||
|
// schema:
|
||||||
|
// "$ref": "#/definitions/UpdateBranchRepoOption"
|
||||||
|
// responses:
|
||||||
|
// "204":
|
||||||
|
// "$ref": "#/responses/empty"
|
||||||
|
// "403":
|
||||||
|
// "$ref": "#/responses/forbidden"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
// "422":
|
||||||
|
// "$ref": "#/responses/validationError"
|
||||||
|
|
||||||
|
opt := web.GetForm(ctx).(*api.UpdateBranchRepoOption)
|
||||||
|
|
||||||
|
oldName := ctx.PathParam("*")
|
||||||
|
repo := ctx.Repo.Repository
|
||||||
|
|
||||||
|
if repo.IsEmpty {
|
||||||
|
ctx.Error(http.StatusNotFound, "", "Git Repository is empty.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if repo.IsMirror {
|
||||||
|
ctx.Error(http.StatusForbidden, "", "Git Repository is a mirror.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
msg, err := repo_service.RenameBranch(ctx, repo, ctx.Doer, ctx.Repo.GitRepo, oldName, opt.Name)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "RenameBranch", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if msg == "target_exist" {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "", "Cannot rename a branch using the same name or rename to a branch that already exists.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if msg == "from_not_exist" {
|
||||||
|
ctx.Error(http.StatusNotFound, "", "Branch doesn't exist.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusNoContent)
|
||||||
|
}
|
||||||
|
|
||||||
// GetBranchProtection gets a branch protection
|
// GetBranchProtection gets a branch protection
|
||||||
func GetBranchProtection(ctx *context.APIContext) {
|
func GetBranchProtection(ctx *context.APIContext) {
|
||||||
// swagger:operation GET /repos/{owner}/{repo}/branch_protections/{name} repository repoGetBranchProtection
|
// swagger:operation GET /repos/{owner}/{repo}/branch_protections/{name} repository repoGetBranchProtection
|
||||||
|
@ -391,8 +391,7 @@ func CreatePullRequest(ctx *context.APIContext) {
|
|||||||
|
|
||||||
form := *web.GetForm(ctx).(*api.CreatePullRequestOption)
|
form := *web.GetForm(ctx).(*api.CreatePullRequestOption)
|
||||||
if form.Head == form.Base {
|
if form.Head == form.Base {
|
||||||
ctx.Error(http.StatusUnprocessableEntity, "BaseHeadSame",
|
ctx.Error(http.StatusUnprocessableEntity, "BaseHeadSame", "Invalid PullRequest: There are no changes between the head and the base")
|
||||||
"Invalid PullRequest: There are no changes between the head and the base")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +90,8 @@ type swaggerParameterBodies struct {
|
|||||||
// in:body
|
// in:body
|
||||||
EditRepoOption api.EditRepoOption
|
EditRepoOption api.EditRepoOption
|
||||||
// in:body
|
// in:body
|
||||||
|
UpdateBranchRepoOption api.UpdateBranchRepoOption
|
||||||
|
// in:body
|
||||||
TransferRepoOption api.TransferRepoOption
|
TransferRepoOption api.TransferRepoOption
|
||||||
// in:body
|
// in:body
|
||||||
CreateForkOption api.CreateForkOption
|
CreateForkOption api.CreateForkOption
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -114,7 +113,6 @@ func MustAllowPulls(ctx *context.Context) {
|
|||||||
// User can send pull request if owns a forked repository.
|
// User can send pull request if owns a forked repository.
|
||||||
if ctx.IsSigned && repo_model.HasForkedRepo(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID) {
|
if ctx.IsSigned && repo_model.HasForkedRepo(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID) {
|
||||||
ctx.Repo.PullRequest.Allowed = true
|
ctx.Repo.PullRequest.Allowed = true
|
||||||
ctx.Repo.PullRequest.HeadInfoSubURL = url.PathEscape(ctx.Doer.Name) + ":" + util.PathEscapeSegments(ctx.Repo.BranchName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,10 +39,9 @@ import (
|
|||||||
|
|
||||||
// PullRequest contains information to make a pull request
|
// PullRequest contains information to make a pull request
|
||||||
type PullRequest struct {
|
type PullRequest struct {
|
||||||
BaseRepo *repo_model.Repository
|
BaseRepo *repo_model.Repository
|
||||||
Allowed bool
|
Allowed bool // it only used by the web tmpl: "PullRequestCtx.Allowed"
|
||||||
SameRepo bool
|
SameRepo bool // it only used by the web tmpl: "PullRequestCtx.SameRepo"
|
||||||
HeadInfoSubURL string // [<user>:]<branch> url segment
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repository contains information to operate a repository
|
// Repository contains information to operate a repository
|
||||||
@ -401,6 +400,7 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
|
|||||||
// RepoAssignment returns a middleware to handle repository assignment
|
// RepoAssignment returns a middleware to handle repository assignment
|
||||||
func RepoAssignment(ctx *Context) context.CancelFunc {
|
func RepoAssignment(ctx *Context) context.CancelFunc {
|
||||||
if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce {
|
if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce {
|
||||||
|
// FIXME: it should panic in dev/test modes to have a clear behavior
|
||||||
log.Trace("RepoAssignment was exec already, skipping second call ...")
|
log.Trace("RepoAssignment was exec already, skipping second call ...")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -697,7 +697,6 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
|
|||||||
ctx.Data["BaseRepo"] = repo.BaseRepo
|
ctx.Data["BaseRepo"] = repo.BaseRepo
|
||||||
ctx.Repo.PullRequest.BaseRepo = repo.BaseRepo
|
ctx.Repo.PullRequest.BaseRepo = repo.BaseRepo
|
||||||
ctx.Repo.PullRequest.Allowed = canPush
|
ctx.Repo.PullRequest.Allowed = canPush
|
||||||
ctx.Repo.PullRequest.HeadInfoSubURL = url.PathEscape(ctx.Repo.Owner.Name) + ":" + util.PathEscapeSegments(ctx.Repo.BranchName)
|
|
||||||
} else if repo.AllowsPulls(ctx) {
|
} else if repo.AllowsPulls(ctx) {
|
||||||
// Or, this is repository accepts pull requests between branches.
|
// Or, this is repository accepts pull requests between branches.
|
||||||
canCompare = true
|
canCompare = true
|
||||||
@ -705,7 +704,6 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
|
|||||||
ctx.Repo.PullRequest.BaseRepo = repo
|
ctx.Repo.PullRequest.BaseRepo = repo
|
||||||
ctx.Repo.PullRequest.Allowed = canPush
|
ctx.Repo.PullRequest.Allowed = canPush
|
||||||
ctx.Repo.PullRequest.SameRepo = true
|
ctx.Repo.PullRequest.SameRepo = true
|
||||||
ctx.Repo.PullRequest.HeadInfoSubURL = util.PathEscapeSegments(ctx.Repo.BranchName)
|
|
||||||
}
|
}
|
||||||
ctx.Data["CanCompareOrPull"] = canCompare
|
ctx.Data["CanCompareOrPull"] = canCompare
|
||||||
ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
|
ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest
|
||||||
@ -771,20 +769,6 @@ func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func isStringLikelyCommitID(objFmt git.ObjectFormat, s string, minLength ...int) bool {
|
|
||||||
minLen := util.OptionalArg(minLength, objFmt.FullLength())
|
|
||||||
if len(s) < minLen || len(s) > objFmt.FullLength() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, c := range s {
|
|
||||||
isHex := (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
|
|
||||||
if !isHex {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRefNameLegacy(ctx *Base, repo *Repository, optionalExtraRef ...string) (string, RepoRefType) {
|
func getRefNameLegacy(ctx *Base, repo *Repository, optionalExtraRef ...string) (string, RepoRefType) {
|
||||||
extraRef := util.OptionalArg(optionalExtraRef)
|
extraRef := util.OptionalArg(optionalExtraRef)
|
||||||
reqPath := ctx.PathParam("*")
|
reqPath := ctx.PathParam("*")
|
||||||
@ -799,7 +783,7 @@ func getRefNameLegacy(ctx *Base, repo *Repository, optionalExtraRef ...string) (
|
|||||||
|
|
||||||
// For legacy support only full commit sha
|
// For legacy support only full commit sha
|
||||||
parts := strings.Split(reqPath, "/")
|
parts := strings.Split(reqPath, "/")
|
||||||
if isStringLikelyCommitID(git.ObjectFormatFromName(repo.Repository.ObjectFormatName), parts[0]) {
|
if git.IsStringLikelyCommitID(git.ObjectFormatFromName(repo.Repository.ObjectFormatName), parts[0]) {
|
||||||
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
|
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
|
||||||
repo.TreePath = strings.Join(parts[1:], "/")
|
repo.TreePath = strings.Join(parts[1:], "/")
|
||||||
return parts[0], RepoRefCommit
|
return parts[0], RepoRefCommit
|
||||||
@ -849,7 +833,7 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
|
|||||||
return getRefNameFromPath(repo, path, repo.GitRepo.IsTagExist)
|
return getRefNameFromPath(repo, path, repo.GitRepo.IsTagExist)
|
||||||
case RepoRefCommit:
|
case RepoRefCommit:
|
||||||
parts := strings.Split(path, "/")
|
parts := strings.Split(path, "/")
|
||||||
if isStringLikelyCommitID(repo.GetObjectFormat(), parts[0], 7) {
|
if git.IsStringLikelyCommitID(repo.GetObjectFormat(), parts[0], 7) {
|
||||||
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
|
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
|
||||||
repo.TreePath = strings.Join(parts[1:], "/")
|
repo.TreePath = strings.Join(parts[1:], "/")
|
||||||
return parts[0]
|
return parts[0]
|
||||||
@ -985,7 +969,7 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
|||||||
return cancel
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||||
} else if isStringLikelyCommitID(ctx.Repo.GetObjectFormat(), refName, 7) {
|
} else if git.IsStringLikelyCommitID(ctx.Repo.GetObjectFormat(), refName, 7) {
|
||||||
ctx.Repo.IsViewCommit = true
|
ctx.Repo.IsViewCommit = true
|
||||||
ctx.Repo.CommitID = refName
|
ctx.Repo.CommitID = refName
|
||||||
|
|
||||||
|
73
templates/swagger/v1_json.tmpl
generated
73
templates/swagger/v1_json.tmpl
generated
@ -5045,6 +5045,63 @@
|
|||||||
"$ref": "#/responses/repoArchivedError"
|
"$ref": "#/responses/repoArchivedError"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"patch": {
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"repository"
|
||||||
|
],
|
||||||
|
"summary": "Update a branch",
|
||||||
|
"operationId": "repoUpdateBranch",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "owner of the repo",
|
||||||
|
"name": "owner",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the repo",
|
||||||
|
"name": "repo",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the branch",
|
||||||
|
"name": "branch",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/UpdateBranchRepoOption"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"$ref": "#/responses/empty"
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"$ref": "#/responses/forbidden"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFound"
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"$ref": "#/responses/validationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/repos/{owner}/{repo}/collaborators": {
|
"/repos/{owner}/{repo}/collaborators": {
|
||||||
@ -24968,6 +25025,22 @@
|
|||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
},
|
},
|
||||||
|
"UpdateBranchRepoOption": {
|
||||||
|
"description": "UpdateBranchRepoOption options when updating a branch in a repository",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "New branch name",
|
||||||
|
"type": "string",
|
||||||
|
"uniqueItems": true,
|
||||||
|
"x-go-name": "Name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
},
|
||||||
"UpdateFileOptions": {
|
"UpdateFileOptions": {
|
||||||
"description": "UpdateFileOptions options for updating files\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)",
|
"description": "UpdateFileOptions options for updating files\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -5,6 +5,7 @@ package integration
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -186,6 +187,37 @@ func testAPICreateBranch(t testing.TB, session *TestSession, user, repo, oldBran
|
|||||||
return resp.Result().StatusCode == status
|
return resp.Result().StatusCode == status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPIUpdateBranch(t *testing.T) {
|
||||||
|
onGiteaRun(t, func(t *testing.T, _ *url.URL) {
|
||||||
|
t.Run("UpdateBranchWithEmptyRepo", func(t *testing.T) {
|
||||||
|
testAPIUpdateBranch(t, "user10", "repo6", "master", "test", http.StatusNotFound)
|
||||||
|
})
|
||||||
|
t.Run("UpdateBranchWithSameBranchNames", func(t *testing.T) {
|
||||||
|
resp := testAPIUpdateBranch(t, "user2", "repo1", "master", "master", http.StatusUnprocessableEntity)
|
||||||
|
assert.Contains(t, resp.Body.String(), "Cannot rename a branch using the same name or rename to a branch that already exists.")
|
||||||
|
})
|
||||||
|
t.Run("UpdateBranchThatAlreadyExists", func(t *testing.T) {
|
||||||
|
resp := testAPIUpdateBranch(t, "user2", "repo1", "master", "branch2", http.StatusUnprocessableEntity)
|
||||||
|
assert.Contains(t, resp.Body.String(), "Cannot rename a branch using the same name or rename to a branch that already exists.")
|
||||||
|
})
|
||||||
|
t.Run("UpdateBranchWithNonExistentBranch", func(t *testing.T) {
|
||||||
|
resp := testAPIUpdateBranch(t, "user2", "repo1", "i-dont-exist", "new-branch-name", http.StatusNotFound)
|
||||||
|
assert.Contains(t, resp.Body.String(), "Branch doesn't exist.")
|
||||||
|
})
|
||||||
|
t.Run("RenameBranchNormalScenario", func(t *testing.T) {
|
||||||
|
testAPIUpdateBranch(t, "user2", "repo1", "branch2", "new-branch-name", http.StatusNoContent)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAPIUpdateBranch(t *testing.T, ownerName, repoName, from, to string, expectedHTTPStatus int) *httptest.ResponseRecorder {
|
||||||
|
token := getUserToken(t, ownerName, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
req := NewRequestWithJSON(t, "PATCH", "api/v1/repos/"+ownerName+"/"+repoName+"/branches/"+from, &api.UpdateBranchRepoOption{
|
||||||
|
Name: to,
|
||||||
|
}).AddTokenAuth(token)
|
||||||
|
return MakeRequest(t, req, expectedHTTPStatus)
|
||||||
|
}
|
||||||
|
|
||||||
func TestAPIBranchProtection(t *testing.T) {
|
func TestAPIBranchProtection(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
|
@ -24,15 +24,27 @@ func TestAPICompareBranches(t *testing.T) {
|
|||||||
session := loginUser(t, user.Name)
|
session := loginUser(t, user.Name)
|
||||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||||
|
|
||||||
repoName := "repo20"
|
t.Run("CompareBranches", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo20/compare/add-csv...remove-files-b").AddTokenAuth(token)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
req := NewRequestf(t, "GET", "/api/v1/repos/user2/%s/compare/add-csv...remove-files-b", repoName).
|
var apiResp *api.Compare
|
||||||
AddTokenAuth(token)
|
DecodeJSON(t, resp, &apiResp)
|
||||||
resp := MakeRequest(t, req, http.StatusOK)
|
|
||||||
|
|
||||||
var apiResp *api.Compare
|
assert.Equal(t, 2, apiResp.TotalCommits)
|
||||||
DecodeJSON(t, resp, &apiResp)
|
assert.Len(t, apiResp.Commits, 2)
|
||||||
|
})
|
||||||
|
|
||||||
assert.Equal(t, 2, apiResp.TotalCommits)
|
t.Run("CompareCommits", func(t *testing.T) {
|
||||||
assert.Len(t, apiResp.Commits, 2)
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo20/compare/808038d2f71b0ab02099...c8e31bc7688741a5287f").AddTokenAuth(token)
|
||||||
|
resp := MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
var apiResp *api.Compare
|
||||||
|
DecodeJSON(t, resp, &apiResp)
|
||||||
|
|
||||||
|
assert.Equal(t, 1, apiResp.TotalCommits)
|
||||||
|
assert.Len(t, apiResp.Commits, 1)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -440,7 +440,7 @@ func DecodeJSON(t testing.TB, resp *httptest.ResponseRecorder, v any) {
|
|||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
decoder := json.NewDecoder(resp.Body)
|
decoder := json.NewDecoder(resp.Body)
|
||||||
assert.NoError(t, decoder.Decode(v))
|
require.NoError(t, decoder.Decode(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyJSONSchema(t testing.TB, resp *httptest.ResponseRecorder, schemaFile string) {
|
func VerifyJSONSchema(t testing.TB, resp *httptest.ResponseRecorder, schemaFile string) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
import imageminZopfli from 'imagemin-zopfli'; // eslint-disable-line i/no-unresolved
|
import imageminZopfli from 'imagemin-zopfli'; // eslint-disable-line import-x/no-unresolved
|
||||||
import {loadSVGFromString, Canvas, Rect, util} from 'fabric/node'; // eslint-disable-line i/no-unresolved
|
import {loadSVGFromString, Canvas, Rect, util} from 'fabric/node'; // eslint-disable-line import-x/no-unresolved
|
||||||
import {optimize} from 'svgo';
|
import {optimize} from 'svgo';
|
||||||
import {readFile, writeFile} from 'node:fs/promises';
|
import {readFile, writeFile} from 'node:fs/promises';
|
||||||
import {argv, exit} from 'node:process';
|
import {argv, exit} from 'node:process';
|
||||||
|
@ -178,6 +178,7 @@ export function initTextareaEvents(textarea, dropzoneEl) {
|
|||||||
});
|
});
|
||||||
textarea.addEventListener('drop', (e) => {
|
textarea.addEventListener('drop', (e) => {
|
||||||
if (!e.dataTransfer.files.length) return;
|
if (!e.dataTransfer.files.length) return;
|
||||||
|
if (!dropzoneEl) return;
|
||||||
handleUploadFiles(new TextareaEditor(textarea), dropzoneEl, e.dataTransfer.files, e);
|
handleUploadFiles(new TextareaEditor(textarea), dropzoneEl, e.dataTransfer.files, e);
|
||||||
});
|
});
|
||||||
dropzoneEl?.dropzone.on(DropzoneCustomEventRemovedFile, ({fileUuid}) => {
|
dropzoneEl?.dropzone.on(DropzoneCustomEventRemovedFile, ({fileUuid}) => {
|
||||||
|
@ -75,12 +75,12 @@ function initCloneSchemeUrlSelection(parent: Element) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
updateClonePanelUi();
|
updateClonePanelUi();
|
||||||
|
// tabSsh or tabHttps might not both exist, eg: guest view, or one is disabled by the server
|
||||||
tabSsh.addEventListener('click', () => {
|
tabSsh?.addEventListener('click', () => {
|
||||||
localStorage.setItem('repo-clone-protocol', 'ssh');
|
localStorage.setItem('repo-clone-protocol', 'ssh');
|
||||||
updateClonePanelUi();
|
updateClonePanelUi();
|
||||||
});
|
});
|
||||||
tabHttps.addEventListener('click', () => {
|
tabHttps?.addEventListener('click', () => {
|
||||||
localStorage.setItem('repo-clone-protocol', 'https');
|
localStorage.setItem('repo-clone-protocol', 'https');
|
||||||
updateClonePanelUi();
|
updateClonePanelUi();
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user