mirror of
https://github.com/go-gitea/gitea
synced 2025-01-03 02:25:56 +01:00
Merge branch 'main' into Badge
This commit is contained in:
commit
ae9c0a6e62
13
cmd/hook.go
13
cmd/hook.go
@ -591,8 +591,9 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
// S: ... ...
|
// S: ... ...
|
||||||
// S: flush-pkt
|
// S: flush-pkt
|
||||||
hookOptions := private.HookOptions{
|
hookOptions := private.HookOptions{
|
||||||
UserName: pusherName,
|
UserName: pusherName,
|
||||||
UserID: pusherID,
|
UserID: pusherID,
|
||||||
|
GitPushOptions: make(map[string]string),
|
||||||
}
|
}
|
||||||
hookOptions.OldCommitIDs = make([]string, 0, hookBatchSize)
|
hookOptions.OldCommitIDs = make([]string, 0, hookBatchSize)
|
||||||
hookOptions.NewCommitIDs = make([]string, 0, hookBatchSize)
|
hookOptions.NewCommitIDs = make([]string, 0, hookBatchSize)
|
||||||
@ -617,8 +618,6 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
hookOptions.RefFullNames = append(hookOptions.RefFullNames, git.RefName(t[2]))
|
hookOptions.RefFullNames = append(hookOptions.RefFullNames, git.RefName(t[2]))
|
||||||
}
|
}
|
||||||
|
|
||||||
hookOptions.GitPushOptions = make(map[string]string)
|
|
||||||
|
|
||||||
if hasPushOptions {
|
if hasPushOptions {
|
||||||
for {
|
for {
|
||||||
rs, err = readPktLine(ctx, reader, pktLineTypeUnknow)
|
rs, err = readPktLine(ctx, reader, pktLineTypeUnknow)
|
||||||
@ -629,11 +628,7 @@ Gitea or set your environment appropriately.`, "")
|
|||||||
if rs.Type == pktLineTypeFlush {
|
if rs.Type == pktLineTypeFlush {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
hookOptions.GitPushOptions.AddFromKeyValue(string(rs.Data))
|
||||||
kv := strings.SplitN(string(rs.Data), "=", 2)
|
|
||||||
if len(kv) == 2 {
|
|
||||||
hookOptions.GitPushOptions[kv[0]] = kv[1]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -712,3 +712,24 @@
|
|||||||
type: 3
|
type: 3
|
||||||
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
|
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
|
||||||
created_unix: 946684810
|
created_unix: 946684810
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 108
|
||||||
|
repo_id: 62
|
||||||
|
type: 1
|
||||||
|
config: "{}"
|
||||||
|
created_unix: 946684810
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 109
|
||||||
|
repo_id: 62
|
||||||
|
type: 2
|
||||||
|
config: "{\"EnableTimetracker\":true,\"AllowOnlyContributorsToTrackTime\":true}"
|
||||||
|
created_unix: 946684810
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 110
|
||||||
|
repo_id: 62
|
||||||
|
type: 3
|
||||||
|
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
|
||||||
|
created_unix: 946684810
|
||||||
|
@ -1768,3 +1768,34 @@
|
|||||||
size: 0
|
size: 0
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 62
|
||||||
|
owner_id: 42
|
||||||
|
owner_name: org42
|
||||||
|
lower_name: search-by-path
|
||||||
|
name: search-by-path
|
||||||
|
default_branch: master
|
||||||
|
num_watches: 0
|
||||||
|
num_stars: 0
|
||||||
|
num_forks: 0
|
||||||
|
num_issues: 0
|
||||||
|
num_closed_issues: 0
|
||||||
|
num_pulls: 0
|
||||||
|
num_closed_pulls: 0
|
||||||
|
num_milestones: 0
|
||||||
|
num_closed_milestones: 0
|
||||||
|
num_projects: 0
|
||||||
|
num_closed_projects: 0
|
||||||
|
is_private: false
|
||||||
|
is_empty: false
|
||||||
|
is_archived: false
|
||||||
|
is_mirror: false
|
||||||
|
status: 0
|
||||||
|
is_fork: false
|
||||||
|
fork_id: 0
|
||||||
|
is_template: false
|
||||||
|
template_id: 0
|
||||||
|
size: 0
|
||||||
|
is_fsck_enabled: true
|
||||||
|
close_issues_via_commit_in_any_branch: false
|
||||||
|
@ -1517,3 +1517,40 @@
|
|||||||
repo_admin_change_team_access: false
|
repo_admin_change_team_access: false
|
||||||
theme: ""
|
theme: ""
|
||||||
keep_activity_private: false
|
keep_activity_private: false
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 42
|
||||||
|
lower_name: org42
|
||||||
|
name: org42
|
||||||
|
full_name: Org42
|
||||||
|
email: org42@example.com
|
||||||
|
keep_email_private: false
|
||||||
|
email_notifications_preference: onmention
|
||||||
|
passwd: ZogKvWdyEx:password
|
||||||
|
passwd_hash_algo: dummy
|
||||||
|
must_change_password: false
|
||||||
|
login_source: 0
|
||||||
|
login_name: org42
|
||||||
|
type: 1
|
||||||
|
salt: ZogKvWdyEx
|
||||||
|
max_repo_creation: -1
|
||||||
|
is_active: false
|
||||||
|
is_admin: false
|
||||||
|
is_restricted: false
|
||||||
|
allow_git_hook: false
|
||||||
|
allow_import_local: false
|
||||||
|
allow_create_organization: true
|
||||||
|
prohibit_login: false
|
||||||
|
avatar: avatar42
|
||||||
|
avatar_email: org42@example.com
|
||||||
|
use_custom_avatar: false
|
||||||
|
num_followers: 0
|
||||||
|
num_following: 0
|
||||||
|
num_stars: 0
|
||||||
|
num_repos: 1
|
||||||
|
num_teams: 0
|
||||||
|
num_members: 0
|
||||||
|
visibility: 0
|
||||||
|
repo_admin_change_team_access: false
|
||||||
|
theme: ""
|
||||||
|
keep_activity_private: false
|
||||||
|
@ -138,12 +138,12 @@ func getTestCases() []struct {
|
|||||||
{
|
{
|
||||||
name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
|
name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
|
||||||
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: optional.Some(false)},
|
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: optional.Some(false)},
|
||||||
count: 33,
|
count: 34,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
|
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
|
||||||
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: optional.Some(false)},
|
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: optional.Some(false)},
|
||||||
count: 38,
|
count: 39,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
|
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
|
||||||
@ -158,7 +158,7 @@ func getTestCases() []struct {
|
|||||||
{
|
{
|
||||||
name: "AllPublic/PublicRepositoriesOfOrganization",
|
name: "AllPublic/PublicRepositoriesOfOrganization",
|
||||||
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: optional.Some(false), Template: optional.Some(false)},
|
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: optional.Some(false), Template: optional.Some(false)},
|
||||||
count: 33,
|
count: 34,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "AllTemplates",
|
name: "AllTemplates",
|
||||||
|
@ -565,42 +565,43 @@ var (
|
|||||||
".",
|
".",
|
||||||
"..",
|
"..",
|
||||||
".well-known",
|
".well-known",
|
||||||
"admin",
|
|
||||||
"api",
|
"api", // gitea api
|
||||||
"assets",
|
"metrics", // prometheus metrics api
|
||||||
"attachments",
|
"v2", // container registry api
|
||||||
"avatar",
|
|
||||||
"avatars",
|
"assets", // static asset files
|
||||||
"captcha",
|
"attachments", // issue attachments
|
||||||
"commits",
|
|
||||||
"debug",
|
"avatar", // avatar by email hash
|
||||||
"error",
|
"avatars", // user avatars by file name
|
||||||
"explore",
|
|
||||||
"favicon.ico",
|
|
||||||
"ghost",
|
|
||||||
"issues",
|
|
||||||
"login",
|
|
||||||
"manifest.json",
|
|
||||||
"metrics",
|
|
||||||
"milestones",
|
|
||||||
"new",
|
|
||||||
"notifications",
|
|
||||||
"org",
|
|
||||||
"pulls",
|
|
||||||
"raw",
|
|
||||||
"repo",
|
|
||||||
"repo-avatars",
|
"repo-avatars",
|
||||||
"robots.txt",
|
|
||||||
"search",
|
"captcha",
|
||||||
"serviceworker.js",
|
"login", // oauth2 login
|
||||||
"ssh_info",
|
"org", // org create/manage, or "/org/{org}", BUT if an org is named as "invite" then it goes wrong
|
||||||
|
"repo", // repo create/migrate, etc
|
||||||
|
"user", // user login/activate/settings, etc
|
||||||
|
|
||||||
|
"explore",
|
||||||
|
"issues",
|
||||||
|
"pulls",
|
||||||
|
"milestones",
|
||||||
|
"notifications",
|
||||||
|
|
||||||
|
"favicon.ico",
|
||||||
|
"manifest.json", // web app manifests
|
||||||
|
"robots.txt", // search engine robots
|
||||||
|
"sitemap.xml", // search engine sitemap
|
||||||
|
"ssh_info", // agit info
|
||||||
"swagger.v1.json",
|
"swagger.v1.json",
|
||||||
"user",
|
|
||||||
"v2",
|
"ghost", // reserved name for deleted users (id: -1)
|
||||||
"gitea-actions",
|
"gitea-actions", // gitea builtin user (id: -2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DON'T ADD ANY NEW STUFF, WE SOLVE THIS WITH `/user/{obj}` PATHS!
|
// These names are reserved for user accounts: user's keys, user's rss feed, user's avatar, etc.
|
||||||
|
// DO NOT add any new stuff! The paths with these names are processed by `/{username}` handler (UsernameSubRoute) manually.
|
||||||
reservedUserPatterns = []string{"*.keys", "*.gpg", "*.rss", "*.atom", "*.png"}
|
reservedUserPatterns = []string{"*.keys", "*.gpg", "*.rss", "*.atom", "*.png"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -92,7 +92,10 @@ func TestSearchUsers(t *testing.T) {
|
|||||||
testOrgSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 4, PageSize: 2}},
|
testOrgSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 4, PageSize: 2}},
|
||||||
[]int64{26, 41})
|
[]int64{26, 41})
|
||||||
|
|
||||||
testOrgSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 5, PageSize: 2}},
|
testOrgSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 5, PageSize: 2}},
|
||||||
|
[]int64{42})
|
||||||
|
|
||||||
|
testOrgSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 6, PageSize: 2}},
|
||||||
[]int64{})
|
[]int64{})
|
||||||
|
|
||||||
// test users
|
// test users
|
||||||
|
@ -111,12 +111,12 @@ func SetExecutablePath(path string) error {
|
|||||||
|
|
||||||
func ensureGitVersion() error {
|
func ensureGitVersion() error {
|
||||||
if !DefaultFeatures().CheckVersionAtLeast(RequiredVersion) {
|
if !DefaultFeatures().CheckVersionAtLeast(RequiredVersion) {
|
||||||
moreHint := "get git: https://git-scm.com/download/"
|
moreHint := "get git: https://git-scm.com/downloads"
|
||||||
if runtime.GOOS == "linux" {
|
if runtime.GOOS == "linux" {
|
||||||
// there are a lot of CentOS/RHEL users using old git, so we add a special hint for them
|
// there are a lot of CentOS/RHEL users using old git, so we add a special hint for them
|
||||||
if _, err := os.Stat("/etc/redhat-release"); err == nil {
|
if _, err := os.Stat("/etc/redhat-release"); err == nil {
|
||||||
// ius.io is the recommended official(git-scm.com) method to install git
|
// ius.io is the recommended official(git-scm.com) method to install git
|
||||||
moreHint = "get git: https://git-scm.com/download/linux and https://ius.io"
|
moreHint = "get git: https://git-scm.com/downloads/linux and https://ius.io"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", DefaultFeatures().gitVersion.Original(), RequiredVersion, moreHint)
|
return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", DefaultFeatures().gitVersion.Original(), RequiredVersion, moreHint)
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/charset"
|
"code.gitea.io/gitea/modules/charset"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/gitrepo"
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
|
path_filter "code.gitea.io/gitea/modules/indexer/code/bleve/token/path"
|
||||||
"code.gitea.io/gitea/modules/indexer/code/internal"
|
"code.gitea.io/gitea/modules/indexer/code/internal"
|
||||||
indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
|
indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
|
||||||
inner_bleve "code.gitea.io/gitea/modules/indexer/internal/bleve"
|
inner_bleve "code.gitea.io/gitea/modules/indexer/internal/bleve"
|
||||||
@ -53,6 +54,7 @@ type RepoIndexerData struct {
|
|||||||
RepoID int64
|
RepoID int64
|
||||||
CommitID string
|
CommitID string
|
||||||
Content string
|
Content string
|
||||||
|
Filename string
|
||||||
Language string
|
Language string
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
@ -64,8 +66,10 @@ func (d *RepoIndexerData) Type() string {
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
repoIndexerAnalyzer = "repoIndexerAnalyzer"
|
repoIndexerAnalyzer = "repoIndexerAnalyzer"
|
||||||
|
filenameIndexerAnalyzer = "filenameIndexerAnalyzer"
|
||||||
|
filenameIndexerTokenizer = "filenameIndexerTokenizer"
|
||||||
repoIndexerDocType = "repoIndexerDocType"
|
repoIndexerDocType = "repoIndexerDocType"
|
||||||
repoIndexerLatestVersion = 6
|
repoIndexerLatestVersion = 7
|
||||||
)
|
)
|
||||||
|
|
||||||
// generateBleveIndexMapping generates a bleve index mapping for the repo indexer
|
// generateBleveIndexMapping generates a bleve index mapping for the repo indexer
|
||||||
@ -79,6 +83,11 @@ func generateBleveIndexMapping() (mapping.IndexMapping, error) {
|
|||||||
textFieldMapping.IncludeInAll = false
|
textFieldMapping.IncludeInAll = false
|
||||||
docMapping.AddFieldMappingsAt("Content", textFieldMapping)
|
docMapping.AddFieldMappingsAt("Content", textFieldMapping)
|
||||||
|
|
||||||
|
fileNamedMapping := bleve.NewTextFieldMapping()
|
||||||
|
fileNamedMapping.IncludeInAll = false
|
||||||
|
fileNamedMapping.Analyzer = filenameIndexerAnalyzer
|
||||||
|
docMapping.AddFieldMappingsAt("Filename", fileNamedMapping)
|
||||||
|
|
||||||
termFieldMapping := bleve.NewTextFieldMapping()
|
termFieldMapping := bleve.NewTextFieldMapping()
|
||||||
termFieldMapping.IncludeInAll = false
|
termFieldMapping.IncludeInAll = false
|
||||||
termFieldMapping.Analyzer = analyzer_keyword.Name
|
termFieldMapping.Analyzer = analyzer_keyword.Name
|
||||||
@ -90,6 +99,7 @@ func generateBleveIndexMapping() (mapping.IndexMapping, error) {
|
|||||||
docMapping.AddFieldMappingsAt("UpdatedAt", timeFieldMapping)
|
docMapping.AddFieldMappingsAt("UpdatedAt", timeFieldMapping)
|
||||||
|
|
||||||
mapping := bleve.NewIndexMapping()
|
mapping := bleve.NewIndexMapping()
|
||||||
|
|
||||||
if err := addUnicodeNormalizeTokenFilter(mapping); err != nil {
|
if err := addUnicodeNormalizeTokenFilter(mapping); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if err := mapping.AddCustomAnalyzer(repoIndexerAnalyzer, map[string]any{
|
} else if err := mapping.AddCustomAnalyzer(repoIndexerAnalyzer, map[string]any{
|
||||||
@ -100,6 +110,16 @@ func generateBleveIndexMapping() (mapping.IndexMapping, error) {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := mapping.AddCustomAnalyzer(filenameIndexerAnalyzer, map[string]any{
|
||||||
|
"type": analyzer_custom.Name,
|
||||||
|
"char_filters": []string{},
|
||||||
|
"tokenizer": unicode.Name,
|
||||||
|
"token_filters": []string{unicodeNormalizeName, path_filter.Name, lowercase.Name},
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
mapping.DefaultAnalyzer = repoIndexerAnalyzer
|
mapping.DefaultAnalyzer = repoIndexerAnalyzer
|
||||||
mapping.AddDocumentMapping(repoIndexerDocType, docMapping)
|
mapping.AddDocumentMapping(repoIndexerDocType, docMapping)
|
||||||
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
mapping.AddDocumentMapping("_all", bleve.NewDocumentDisabledMapping())
|
||||||
@ -174,6 +194,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro
|
|||||||
return batch.Index(id, &RepoIndexerData{
|
return batch.Index(id, &RepoIndexerData{
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
CommitID: commitSha,
|
CommitID: commitSha,
|
||||||
|
Filename: update.Filename,
|
||||||
Content: string(charset.ToUTF8DropErrors(fileContents, charset.ConvertOpts{})),
|
Content: string(charset.ToUTF8DropErrors(fileContents, charset.ConvertOpts{})),
|
||||||
Language: analyze.GetCodeLanguage(update.Filename, fileContents),
|
Language: analyze.GetCodeLanguage(update.Filename, fileContents),
|
||||||
UpdatedAt: time.Now().UTC(),
|
UpdatedAt: time.Now().UTC(),
|
||||||
@ -240,14 +261,19 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
|||||||
keywordQuery query.Query
|
keywordQuery query.Query
|
||||||
)
|
)
|
||||||
|
|
||||||
phraseQuery := bleve.NewMatchPhraseQuery(opts.Keyword)
|
pathQuery := bleve.NewPrefixQuery(strings.ToLower(opts.Keyword))
|
||||||
phraseQuery.FieldVal = "Content"
|
pathQuery.FieldVal = "Filename"
|
||||||
phraseQuery.Analyzer = repoIndexerAnalyzer
|
pathQuery.SetBoost(10)
|
||||||
keywordQuery = phraseQuery
|
|
||||||
|
contentQuery := bleve.NewMatchQuery(opts.Keyword)
|
||||||
|
contentQuery.FieldVal = "Content"
|
||||||
|
|
||||||
if opts.IsKeywordFuzzy {
|
if opts.IsKeywordFuzzy {
|
||||||
phraseQuery.Fuzziness = inner_bleve.GuessFuzzinessByKeyword(opts.Keyword)
|
contentQuery.Fuzziness = inner_bleve.GuessFuzzinessByKeyword(opts.Keyword)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keywordQuery = bleve.NewDisjunctionQuery(contentQuery, pathQuery)
|
||||||
|
|
||||||
if len(opts.RepoIDs) > 0 {
|
if len(opts.RepoIDs) > 0 {
|
||||||
repoQueries := make([]query.Query, 0, len(opts.RepoIDs))
|
repoQueries := make([]query.Query, 0, len(opts.RepoIDs))
|
||||||
for _, repoID := range opts.RepoIDs {
|
for _, repoID := range opts.RepoIDs {
|
||||||
@ -277,7 +303,7 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
|||||||
|
|
||||||
from, pageSize := opts.GetSkipTake()
|
from, pageSize := opts.GetSkipTake()
|
||||||
searchRequest := bleve.NewSearchRequestOptions(indexerQuery, pageSize, from, false)
|
searchRequest := bleve.NewSearchRequestOptions(indexerQuery, pageSize, from, false)
|
||||||
searchRequest.Fields = []string{"Content", "RepoID", "Language", "CommitID", "UpdatedAt"}
|
searchRequest.Fields = []string{"Content", "Filename", "RepoID", "Language", "CommitID", "UpdatedAt"}
|
||||||
searchRequest.IncludeLocations = true
|
searchRequest.IncludeLocations = true
|
||||||
|
|
||||||
if len(opts.Language) == 0 {
|
if len(opts.Language) == 0 {
|
||||||
@ -307,6 +333,10 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
|||||||
endIndex = locationEnd
|
endIndex = locationEnd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(hit.Locations["Filename"]) > 0 {
|
||||||
|
startIndex, endIndex = internal.FilenameMatchIndexPos(hit.Fields["Content"].(string))
|
||||||
|
}
|
||||||
|
|
||||||
language := hit.Fields["Language"].(string)
|
language := hit.Fields["Language"].(string)
|
||||||
var updatedUnix timeutil.TimeStamp
|
var updatedUnix timeutil.TimeStamp
|
||||||
if t, err := time.Parse(time.RFC3339, hit.Fields["UpdatedAt"].(string)); err == nil {
|
if t, err := time.Parse(time.RFC3339, hit.Fields["UpdatedAt"].(string)); err == nil {
|
||||||
|
101
modules/indexer/code/bleve/token/path/path.go
Normal file
101
modules/indexer/code/bleve/token/path/path.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package path
|
||||||
|
|
||||||
|
import (
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/blevesearch/bleve/v2/analysis"
|
||||||
|
"github.com/blevesearch/bleve/v2/registry"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Name = "gitea/path"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TokenFilter struct{}
|
||||||
|
|
||||||
|
func NewTokenFilter() *TokenFilter {
|
||||||
|
return &TokenFilter{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TokenFilterConstructor(config map[string]any, cache *registry.Cache) (analysis.TokenFilter, error) {
|
||||||
|
return NewTokenFilter(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TokenFilter) Filter(input analysis.TokenStream) analysis.TokenStream {
|
||||||
|
if len(input) == 1 {
|
||||||
|
// if there is only one token, we dont need to generate the reversed chain
|
||||||
|
return generatePathTokens(input, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
normal := generatePathTokens(input, false)
|
||||||
|
reversed := generatePathTokens(input, true)
|
||||||
|
|
||||||
|
return append(normal, reversed...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates path tokens from the input tokens.
|
||||||
|
// This mimics the behavior of the path hierarchy tokenizer in ES. It takes the input tokens and combine them, generating a term for each component
|
||||||
|
// in tree (e.g., foo/bar/baz.md will generate foo, foo/bar, and foo/bar/baz.md).
|
||||||
|
//
|
||||||
|
// If the reverse flag is set, the order of the tokens is reversed (the same input will generate baz.md, baz.md/bar, baz.md/bar/foo). This is useful
|
||||||
|
// to efficiently search for filenames without supplying the fullpath.
|
||||||
|
func generatePathTokens(input analysis.TokenStream, reversed bool) analysis.TokenStream {
|
||||||
|
terms := make([]string, 0, len(input))
|
||||||
|
longestTerm := 0
|
||||||
|
|
||||||
|
if reversed {
|
||||||
|
slices.Reverse(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(input); i++ {
|
||||||
|
var sb strings.Builder
|
||||||
|
sb.WriteString(string(input[0].Term))
|
||||||
|
|
||||||
|
for j := 1; j < i; j++ {
|
||||||
|
sb.WriteString("/")
|
||||||
|
sb.WriteString(string(input[j].Term))
|
||||||
|
}
|
||||||
|
|
||||||
|
term := sb.String()
|
||||||
|
|
||||||
|
if longestTerm < len(term) {
|
||||||
|
longestTerm = len(term)
|
||||||
|
}
|
||||||
|
|
||||||
|
terms = append(terms, term)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := make(analysis.TokenStream, 0, len(terms))
|
||||||
|
|
||||||
|
for _, term := range terms {
|
||||||
|
var start, end int
|
||||||
|
|
||||||
|
if reversed {
|
||||||
|
start = 0
|
||||||
|
end = len(term)
|
||||||
|
} else {
|
||||||
|
start = longestTerm - len(term)
|
||||||
|
end = longestTerm
|
||||||
|
}
|
||||||
|
|
||||||
|
token := analysis.Token{
|
||||||
|
Position: 1,
|
||||||
|
Start: start,
|
||||||
|
End: end,
|
||||||
|
Type: analysis.AlphaNumeric,
|
||||||
|
Term: []byte(term),
|
||||||
|
}
|
||||||
|
|
||||||
|
output = append(output, &token)
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registry.RegisterTokenFilter(Name, TokenFilterConstructor)
|
||||||
|
}
|
76
modules/indexer/code/bleve/token/path/path_test.go
Normal file
76
modules/indexer/code/bleve/token/path/path_test.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package path
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/blevesearch/bleve/v2/analysis"
|
||||||
|
"github.com/blevesearch/bleve/v2/analysis/tokenizer/unicode"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Scenario struct {
|
||||||
|
Input string
|
||||||
|
Tokens []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTokenFilter(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
Input string
|
||||||
|
Terms []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "Dockerfile",
|
||||||
|
Terms: []string{"Dockerfile"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Dockerfile.rootless",
|
||||||
|
Terms: []string{"Dockerfile.rootless"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "a/b/c/Dockerfile.rootless",
|
||||||
|
Terms: []string{"a", "a/b", "a/b/c", "a/b/c/Dockerfile.rootless", "Dockerfile.rootless", "Dockerfile.rootless/c", "Dockerfile.rootless/c/b", "Dockerfile.rootless/c/b/a"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "",
|
||||||
|
Terms: []string{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, scenario := range scenarios {
|
||||||
|
t.Run(fmt.Sprintf("ensure terms of '%s'", scenario.Input), func(t *testing.T) {
|
||||||
|
terms := extractTerms(scenario.Input)
|
||||||
|
|
||||||
|
assert.Len(t, terms, len(scenario.Terms))
|
||||||
|
|
||||||
|
for _, term := range terms {
|
||||||
|
assert.Contains(t, scenario.Terms, term)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractTerms(input string) []string {
|
||||||
|
tokens := tokenize(input)
|
||||||
|
filteredTokens := filter(tokens)
|
||||||
|
terms := make([]string, 0, len(filteredTokens))
|
||||||
|
|
||||||
|
for _, token := range filteredTokens {
|
||||||
|
terms = append(terms, string(token.Term))
|
||||||
|
}
|
||||||
|
|
||||||
|
return terms
|
||||||
|
}
|
||||||
|
|
||||||
|
func filter(input analysis.TokenStream) analysis.TokenStream {
|
||||||
|
filter := NewTokenFilter()
|
||||||
|
return filter.Filter(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tokenize(input string) analysis.TokenStream {
|
||||||
|
tokenizer := unicode.NewUnicodeTokenizer()
|
||||||
|
return tokenizer.Tokenize([]byte(input))
|
||||||
|
}
|
@ -30,7 +30,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
esRepoIndexerLatestVersion = 1
|
esRepoIndexerLatestVersion = 2
|
||||||
// multi-match-types, currently only 2 types are used
|
// multi-match-types, currently only 2 types are used
|
||||||
// Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html#multi-match-types
|
// Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html#multi-match-types
|
||||||
esMultiMatchTypeBestFields = "best_fields"
|
esMultiMatchTypeBestFields = "best_fields"
|
||||||
@ -57,12 +57,50 @@ func NewIndexer(url, indexerName string) *Indexer {
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
defaultMapping = `{
|
defaultMapping = `{
|
||||||
|
"settings": {
|
||||||
|
"analysis": {
|
||||||
|
"analyzer": {
|
||||||
|
"filename_path_analyzer": {
|
||||||
|
"tokenizer": "path_tokenizer"
|
||||||
|
},
|
||||||
|
"reversed_filename_path_analyzer": {
|
||||||
|
"tokenizer": "reversed_path_tokenizer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tokenizer": {
|
||||||
|
"path_tokenizer": {
|
||||||
|
"type": "path_hierarchy",
|
||||||
|
"delimiter": "/"
|
||||||
|
},
|
||||||
|
"reversed_path_tokenizer": {
|
||||||
|
"type": "path_hierarchy",
|
||||||
|
"delimiter": "/",
|
||||||
|
"reverse": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"mappings": {
|
"mappings": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"repo_id": {
|
"repo_id": {
|
||||||
"type": "long",
|
"type": "long",
|
||||||
"index": true
|
"index": true
|
||||||
},
|
},
|
||||||
|
"filename": {
|
||||||
|
"type": "text",
|
||||||
|
"term_vector": "with_positions_offsets",
|
||||||
|
"index": true,
|
||||||
|
"fields": {
|
||||||
|
"path": {
|
||||||
|
"type": "text",
|
||||||
|
"analyzer": "reversed_filename_path_analyzer"
|
||||||
|
},
|
||||||
|
"path_reversed": {
|
||||||
|
"type": "text",
|
||||||
|
"analyzer": "filename_path_analyzer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"content": {
|
"content": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"term_vector": "with_positions_offsets",
|
"term_vector": "with_positions_offsets",
|
||||||
@ -136,6 +174,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro
|
|||||||
Id(id).
|
Id(id).
|
||||||
Doc(map[string]any{
|
Doc(map[string]any{
|
||||||
"repo_id": repo.ID,
|
"repo_id": repo.ID,
|
||||||
|
"filename": update.Filename,
|
||||||
"content": string(charset.ToUTF8DropErrors(fileContents, charset.ConvertOpts{})),
|
"content": string(charset.ToUTF8DropErrors(fileContents, charset.ConvertOpts{})),
|
||||||
"commit_id": sha,
|
"commit_id": sha,
|
||||||
"language": analyze.GetCodeLanguage(update.Filename, fileContents),
|
"language": analyze.GetCodeLanguage(update.Filename, fileContents),
|
||||||
@ -231,11 +270,11 @@ func (b *Indexer) doDelete(ctx context.Context, repoID int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexPos find words positions for start and the following end on content. It will
|
// contentMatchIndexPos find words positions for start and the following end on content. It will
|
||||||
// return the beginning position of the first start and the ending position of the
|
// return the beginning position of the first start and the ending position of the
|
||||||
// first end following the start string.
|
// first end following the start string.
|
||||||
// If not found any of the positions, it will return -1, -1.
|
// If not found any of the positions, it will return -1, -1.
|
||||||
func indexPos(content, start, end string) (int, int) {
|
func contentMatchIndexPos(content, start, end string) (int, int) {
|
||||||
startIdx := strings.Index(content, start)
|
startIdx := strings.Index(content, start)
|
||||||
if startIdx < 0 {
|
if startIdx < 0 {
|
||||||
return -1, -1
|
return -1, -1
|
||||||
@ -244,22 +283,29 @@ func indexPos(content, start, end string) (int, int) {
|
|||||||
if endIdx < 0 {
|
if endIdx < 0 {
|
||||||
return -1, -1
|
return -1, -1
|
||||||
}
|
}
|
||||||
return startIdx, startIdx + len(start) + endIdx + len(end)
|
return startIdx, (startIdx + len(start) + endIdx + len(end)) - 9 // remove the length <em></em> since we give Content the original data
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertResult(searchResult *elastic.SearchResult, kw string, pageSize int) (int64, []*internal.SearchResult, []*internal.SearchResultLanguages, error) {
|
func convertResult(searchResult *elastic.SearchResult, kw string, pageSize int) (int64, []*internal.SearchResult, []*internal.SearchResultLanguages, error) {
|
||||||
hits := make([]*internal.SearchResult, 0, pageSize)
|
hits := make([]*internal.SearchResult, 0, pageSize)
|
||||||
for _, hit := range searchResult.Hits.Hits {
|
for _, hit := range searchResult.Hits.Hits {
|
||||||
|
repoID, fileName := internal.ParseIndexerID(hit.Id)
|
||||||
|
res := make(map[string]any)
|
||||||
|
if err := json.Unmarshal(hit.Source, &res); err != nil {
|
||||||
|
return 0, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: There is no way to get the position the keyword on the content currently on the same request.
|
// FIXME: There is no way to get the position the keyword on the content currently on the same request.
|
||||||
// So we get it from content, this may made the query slower. See
|
// So we get it from content, this may made the query slower. See
|
||||||
// https://discuss.elastic.co/t/fetching-position-of-keyword-in-matched-document/94291
|
// https://discuss.elastic.co/t/fetching-position-of-keyword-in-matched-document/94291
|
||||||
var startIndex, endIndex int
|
var startIndex, endIndex int
|
||||||
c, ok := hit.Highlight["content"]
|
if c, ok := hit.Highlight["filename"]; ok && len(c) > 0 {
|
||||||
if ok && len(c) > 0 {
|
startIndex, endIndex = internal.FilenameMatchIndexPos(res["content"].(string))
|
||||||
|
} else if c, ok := hit.Highlight["content"]; ok && len(c) > 0 {
|
||||||
// FIXME: Since the highlighting content will include <em> and </em> for the keywords,
|
// FIXME: Since the highlighting content will include <em> and </em> for the keywords,
|
||||||
// now we should find the positions. But how to avoid html content which contains the
|
// now we should find the positions. But how to avoid html content which contains the
|
||||||
// <em> and </em> tags? If elastic search has handled that?
|
// <em> and </em> tags? If elastic search has handled that?
|
||||||
startIndex, endIndex = indexPos(c[0], "<em>", "</em>")
|
startIndex, endIndex = contentMatchIndexPos(c[0], "<em>", "</em>")
|
||||||
if startIndex == -1 {
|
if startIndex == -1 {
|
||||||
panic(fmt.Sprintf("1===%s,,,%#v,,,%s", kw, hit.Highlight, c[0]))
|
panic(fmt.Sprintf("1===%s,,,%#v,,,%s", kw, hit.Highlight, c[0]))
|
||||||
}
|
}
|
||||||
@ -267,12 +313,6 @@ func convertResult(searchResult *elastic.SearchResult, kw string, pageSize int)
|
|||||||
panic(fmt.Sprintf("2===%#v", hit.Highlight))
|
panic(fmt.Sprintf("2===%#v", hit.Highlight))
|
||||||
}
|
}
|
||||||
|
|
||||||
repoID, fileName := internal.ParseIndexerID(hit.Id)
|
|
||||||
res := make(map[string]any)
|
|
||||||
if err := json.Unmarshal(hit.Source, &res); err != nil {
|
|
||||||
return 0, nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
language := res["language"].(string)
|
language := res["language"].(string)
|
||||||
|
|
||||||
hits = append(hits, &internal.SearchResult{
|
hits = append(hits, &internal.SearchResult{
|
||||||
@ -283,7 +323,7 @@ func convertResult(searchResult *elastic.SearchResult, kw string, pageSize int)
|
|||||||
UpdatedUnix: timeutil.TimeStamp(res["updated_at"].(float64)),
|
UpdatedUnix: timeutil.TimeStamp(res["updated_at"].(float64)),
|
||||||
Language: language,
|
Language: language,
|
||||||
StartIndex: startIndex,
|
StartIndex: startIndex,
|
||||||
EndIndex: endIndex - 9, // remove the length <em></em> since we give Content the original data
|
EndIndex: endIndex,
|
||||||
Color: enry.GetColor(language),
|
Color: enry.GetColor(language),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -315,7 +355,10 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
|||||||
searchType = esMultiMatchTypeBestFields
|
searchType = esMultiMatchTypeBestFields
|
||||||
}
|
}
|
||||||
|
|
||||||
kwQuery := elastic.NewMultiMatchQuery(opts.Keyword, "content").Type(searchType)
|
kwQuery := elastic.NewBoolQuery().Should(
|
||||||
|
elastic.NewMultiMatchQuery(opts.Keyword, "content").Type(searchType),
|
||||||
|
elastic.NewMultiMatchQuery(opts.Keyword, "filename^10").Type(esMultiMatchTypePhrasePrefix),
|
||||||
|
)
|
||||||
query := elastic.NewBoolQuery()
|
query := elastic.NewBoolQuery()
|
||||||
query = query.Must(kwQuery)
|
query = query.Must(kwQuery)
|
||||||
if len(opts.RepoIDs) > 0 {
|
if len(opts.RepoIDs) > 0 {
|
||||||
@ -341,6 +384,7 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
|||||||
Highlight(
|
Highlight(
|
||||||
elastic.NewHighlight().
|
elastic.NewHighlight().
|
||||||
Field("content").
|
Field("content").
|
||||||
|
Field("filename").
|
||||||
NumOfFragments(0). // return all highting content on fragments
|
NumOfFragments(0). // return all highting content on fragments
|
||||||
HighlighterType("fvh"),
|
HighlighterType("fvh"),
|
||||||
).
|
).
|
||||||
@ -373,6 +417,7 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
|
|||||||
Highlight(
|
Highlight(
|
||||||
elastic.NewHighlight().
|
elastic.NewHighlight().
|
||||||
Field("content").
|
Field("content").
|
||||||
|
Field("filename").
|
||||||
NumOfFragments(0). // return all highting content on fragments
|
NumOfFragments(0). // return all highting content on fragments
|
||||||
HighlighterType("fvh"),
|
HighlighterType("fvh"),
|
||||||
).
|
).
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestIndexPos(t *testing.T) {
|
func TestIndexPos(t *testing.T) {
|
||||||
startIdx, endIdx := indexPos("test index start and end", "start", "end")
|
startIdx, endIdx := contentMatchIndexPos("test index start and end", "start", "end")
|
||||||
assert.EqualValues(t, 11, startIdx)
|
assert.EqualValues(t, 11, startIdx)
|
||||||
assert.EqualValues(t, 24, endIdx)
|
assert.EqualValues(t, 15, endIdx)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ package code
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
@ -20,53 +21,166 @@ import (
|
|||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type codeSearchResult struct {
|
||||||
|
Filename string
|
||||||
|
Content string
|
||||||
|
}
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
unittest.MainTest(m)
|
unittest.MainTest(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testIndexer(name string, t *testing.T, indexer internal.Indexer) {
|
func testIndexer(name string, t *testing.T, indexer internal.Indexer) {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
var repoID int64 = 1
|
assert.NoError(t, setupRepositoryIndexes(git.DefaultContext, indexer))
|
||||||
err := index(git.DefaultContext, indexer, repoID)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
keywords := []struct {
|
keywords := []struct {
|
||||||
RepoIDs []int64
|
RepoIDs []int64
|
||||||
Keyword string
|
Keyword string
|
||||||
IDs []int64
|
|
||||||
Langs int
|
Langs int
|
||||||
|
Results []codeSearchResult
|
||||||
}{
|
}{
|
||||||
|
// Search for an exact match on the contents of a file
|
||||||
|
// This scenario yields a single result (the file README.md on the repo '1')
|
||||||
{
|
{
|
||||||
RepoIDs: nil,
|
RepoIDs: nil,
|
||||||
Keyword: "Description",
|
Keyword: "Description",
|
||||||
IDs: []int64{repoID},
|
|
||||||
Langs: 1,
|
Langs: 1,
|
||||||
|
Results: []codeSearchResult{
|
||||||
|
{
|
||||||
|
Filename: "README.md",
|
||||||
|
Content: "# repo1\n\nDescription for repo1",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
// Search for an exact match on the contents of a file within the repo '2'.
|
||||||
|
// This scenario yields no results
|
||||||
{
|
{
|
||||||
RepoIDs: []int64{2},
|
RepoIDs: []int64{2},
|
||||||
Keyword: "Description",
|
Keyword: "Description",
|
||||||
IDs: []int64{},
|
|
||||||
Langs: 0,
|
Langs: 0,
|
||||||
},
|
},
|
||||||
|
// Search for an exact match on the contents of a file
|
||||||
|
// This scenario yields a single result (the file README.md on the repo '1')
|
||||||
{
|
{
|
||||||
RepoIDs: nil,
|
RepoIDs: nil,
|
||||||
Keyword: "repo1",
|
Keyword: "repo1",
|
||||||
IDs: []int64{repoID},
|
|
||||||
Langs: 1,
|
Langs: 1,
|
||||||
|
Results: []codeSearchResult{
|
||||||
|
{
|
||||||
|
Filename: "README.md",
|
||||||
|
Content: "# repo1\n\nDescription for repo1",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
// Search for an exact match on the contents of a file within the repo '2'.
|
||||||
|
// This scenario yields no results
|
||||||
{
|
{
|
||||||
RepoIDs: []int64{2},
|
RepoIDs: []int64{2},
|
||||||
Keyword: "repo1",
|
Keyword: "repo1",
|
||||||
IDs: []int64{},
|
|
||||||
Langs: 0,
|
Langs: 0,
|
||||||
},
|
},
|
||||||
|
// Search for a non-existing term.
|
||||||
|
// This scenario yields no results
|
||||||
{
|
{
|
||||||
RepoIDs: nil,
|
RepoIDs: nil,
|
||||||
Keyword: "non-exist",
|
Keyword: "non-exist",
|
||||||
IDs: []int64{},
|
|
||||||
Langs: 0,
|
Langs: 0,
|
||||||
},
|
},
|
||||||
|
// Search for an exact match on the contents of a file within the repo '62'.
|
||||||
|
// This scenario yields a single result (the file avocado.md on the repo '62')
|
||||||
|
{
|
||||||
|
RepoIDs: []int64{62},
|
||||||
|
Keyword: "pineaple",
|
||||||
|
Langs: 1,
|
||||||
|
Results: []codeSearchResult{
|
||||||
|
{
|
||||||
|
Filename: "avocado.md",
|
||||||
|
Content: "# repo1\n\npineaple pie of cucumber juice",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Search for an exact match on the filename within the repo '62'.
|
||||||
|
// This scenario yields a single result (the file avocado.md on the repo '62')
|
||||||
|
{
|
||||||
|
RepoIDs: []int64{62},
|
||||||
|
Keyword: "avocado.md",
|
||||||
|
Langs: 1,
|
||||||
|
Results: []codeSearchResult{
|
||||||
|
{
|
||||||
|
Filename: "avocado.md",
|
||||||
|
Content: "# repo1\n\npineaple pie of cucumber juice",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Search for an partial match on the filename within the repo '62'.
|
||||||
|
// This scenario yields a single result (the file avocado.md on the repo '62')
|
||||||
|
{
|
||||||
|
RepoIDs: []int64{62},
|
||||||
|
Keyword: "avo",
|
||||||
|
Langs: 1,
|
||||||
|
Results: []codeSearchResult{
|
||||||
|
{
|
||||||
|
Filename: "avocado.md",
|
||||||
|
Content: "# repo1\n\npineaple pie of cucumber juice",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Search for matches on both the contents and the filenames within the repo '62'.
|
||||||
|
// This scenario yields two results: the first result is baed on the file (cucumber.md) while the second is based on the contents
|
||||||
|
{
|
||||||
|
RepoIDs: []int64{62},
|
||||||
|
Keyword: "cucumber",
|
||||||
|
Langs: 1,
|
||||||
|
Results: []codeSearchResult{
|
||||||
|
{
|
||||||
|
Filename: "cucumber.md",
|
||||||
|
Content: "Salad is good for your health",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Filename: "avocado.md",
|
||||||
|
Content: "# repo1\n\npineaple pie of cucumber juice",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Search for matches on the filenames within the repo '62'.
|
||||||
|
// This scenario yields two results (both are based on filename, the first one is an exact match)
|
||||||
|
{
|
||||||
|
RepoIDs: []int64{62},
|
||||||
|
Keyword: "ham",
|
||||||
|
Langs: 1,
|
||||||
|
Results: []codeSearchResult{
|
||||||
|
{
|
||||||
|
Filename: "ham.md",
|
||||||
|
Content: "This is also not cheese",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Filename: "potato/ham.md",
|
||||||
|
Content: "This is not cheese",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Search for matches on the contents of files within the repo '62'.
|
||||||
|
// This scenario yields two results (both are based on contents, the first one is an exact match where as the second is a 'fuzzy' one)
|
||||||
|
{
|
||||||
|
RepoIDs: []int64{62},
|
||||||
|
Keyword: "This is not cheese",
|
||||||
|
Langs: 1,
|
||||||
|
Results: []codeSearchResult{
|
||||||
|
{
|
||||||
|
Filename: "potato/ham.md",
|
||||||
|
Content: "This is not cheese",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Filename: "ham.md",
|
||||||
|
Content: "This is also not cheese",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, kw := range keywords {
|
for _, kw := range keywords {
|
||||||
@ -81,19 +195,37 @@ func testIndexer(name string, t *testing.T, indexer internal.Indexer) {
|
|||||||
IsKeywordFuzzy: true,
|
IsKeywordFuzzy: true,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, kw.IDs, int(total))
|
|
||||||
assert.Len(t, langs, kw.Langs)
|
assert.Len(t, langs, kw.Langs)
|
||||||
|
|
||||||
ids := make([]int64, 0, len(res))
|
hits := make([]codeSearchResult, 0, len(res))
|
||||||
for _, hit := range res {
|
|
||||||
ids = append(ids, hit.RepoID)
|
if total > 0 {
|
||||||
assert.EqualValues(t, "# repo1\n\nDescription for repo1", hit.Content)
|
assert.NotEmpty(t, kw.Results, "The given scenario does not provide any expected results")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, hit := range res {
|
||||||
|
hits = append(hits, codeSearchResult{
|
||||||
|
Filename: hit.Filename,
|
||||||
|
Content: hit.Content,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
lastIndex := -1
|
||||||
|
|
||||||
|
for _, expected := range kw.Results {
|
||||||
|
index := slices.Index(hits, expected)
|
||||||
|
if index == -1 {
|
||||||
|
assert.Failf(t, "Result not found", "Expected %v in %v", expected, hits)
|
||||||
|
} else if lastIndex > index {
|
||||||
|
assert.Failf(t, "Result is out of order", "The order of %v within %v is wrong", expected, hits)
|
||||||
|
} else {
|
||||||
|
lastIndex = index
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assert.EqualValues(t, kw.IDs, ids)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.NoError(t, indexer.Delete(context.Background(), repoID))
|
assert.NoError(t, tearDownRepositoryIndexes(indexer))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,3 +268,25 @@ func TestESIndexAndSearch(t *testing.T) {
|
|||||||
|
|
||||||
testIndexer("elastic_search", t, indexer)
|
testIndexer("elastic_search", t, indexer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupRepositoryIndexes(ctx context.Context, indexer internal.Indexer) error {
|
||||||
|
for _, repoID := range repositoriesToSearch() {
|
||||||
|
if err := index(ctx, indexer, repoID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func tearDownRepositoryIndexes(indexer internal.Indexer) error {
|
||||||
|
for _, repoID := range repositoriesToSearch() {
|
||||||
|
if err := indexer.Delete(context.Background(), repoID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func repositoriesToSearch() []int64 {
|
||||||
|
return []int64{1, 62}
|
||||||
|
}
|
||||||
|
@ -10,6 +10,10 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
filenameMatchNumberOfLines = 7 // Copied from github search
|
||||||
|
)
|
||||||
|
|
||||||
func FilenameIndexerID(repoID int64, filename string) string {
|
func FilenameIndexerID(repoID int64, filename string) string {
|
||||||
return internal.Base36(repoID) + "_" + filename
|
return internal.Base36(repoID) + "_" + filename
|
||||||
}
|
}
|
||||||
@ -30,3 +34,17 @@ func FilenameOfIndexerID(indexerID string) string {
|
|||||||
}
|
}
|
||||||
return indexerID[index+1:]
|
return indexerID[index+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Given the contents of file, returns the boundaries of its first seven lines.
|
||||||
|
func FilenameMatchIndexPos(content string) (int, int) {
|
||||||
|
count := 1
|
||||||
|
for i, c := range content {
|
||||||
|
if c == '\n' {
|
||||||
|
count++
|
||||||
|
if count == filenameMatchNumberOfLines {
|
||||||
|
return 0, i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, len(content)
|
||||||
|
}
|
||||||
|
@ -11,10 +11,15 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/blevesearch/bleve/v2"
|
"github.com/blevesearch/bleve/v2"
|
||||||
|
"github.com/blevesearch/bleve/v2/analysis/tokenizer/unicode"
|
||||||
"github.com/blevesearch/bleve/v2/index/upsidedown"
|
"github.com/blevesearch/bleve/v2/index/upsidedown"
|
||||||
"github.com/ethantkoenig/rupture"
|
"github.com/ethantkoenig/rupture"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxFuzziness = 2
|
||||||
|
)
|
||||||
|
|
||||||
// openIndexer open the index at the specified path, checking for metadata
|
// openIndexer open the index at the specified path, checking for metadata
|
||||||
// updates and bleve version updates. If index needs to be created (or
|
// updates and bleve version updates. If index needs to be created (or
|
||||||
// re-created), returns (nil, nil)
|
// re-created), returns (nil, nil)
|
||||||
@ -48,7 +53,27 @@ func openIndexer(path string, latestVersion int) (bleve.Index, int, error) {
|
|||||||
return index, 0, nil
|
return index, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method test the GuessFuzzinessByKeyword method. The fuzziness is based on the levenshtein distance and determines how many chars
|
||||||
|
// may be different on two string and they still be considered equivalent.
|
||||||
|
// Given a phrasse, its shortest word determines its fuzziness. If a phrase uses CJK (eg: `갃갃갃` `啊啊啊`), the fuzziness is zero.
|
||||||
func GuessFuzzinessByKeyword(s string) int {
|
func GuessFuzzinessByKeyword(s string) int {
|
||||||
|
tokenizer := unicode.NewUnicodeTokenizer()
|
||||||
|
tokens := tokenizer.Tokenize([]byte(s))
|
||||||
|
|
||||||
|
if len(tokens) > 0 {
|
||||||
|
fuzziness := maxFuzziness
|
||||||
|
|
||||||
|
for _, token := range tokens {
|
||||||
|
fuzziness = min(fuzziness, guessFuzzinessByKeyword(string(token.Term)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return fuzziness
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func guessFuzzinessByKeyword(s string) int {
|
||||||
// according to https://github.com/blevesearch/bleve/issues/1563, the supported max fuzziness is 2
|
// according to https://github.com/blevesearch/bleve/issues/1563, the supported max fuzziness is 2
|
||||||
// magic number 4 was chosen to determine the levenshtein distance per each character of a keyword
|
// magic number 4 was chosen to determine the levenshtein distance per each character of a keyword
|
||||||
// BUT, when using CJK (eg: `갃갃갃` `啊啊啊`), it mismatches a lot.
|
// BUT, when using CJK (eg: `갃갃갃` `啊啊啊`), it mismatches a lot.
|
||||||
@ -57,5 +82,5 @@ func GuessFuzzinessByKeyword(s string) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return min(2, len(s)/4)
|
return min(maxFuzziness, len(s)/4)
|
||||||
}
|
}
|
||||||
|
45
modules/indexer/internal/bleve/util_test.go
Normal file
45
modules/indexer/internal/bleve/util_test.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package bleve
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBleveGuessFuzzinessByKeyword(t *testing.T) {
|
||||||
|
scenarios := []struct {
|
||||||
|
Input string
|
||||||
|
Fuzziness int // See util.go for the definition of fuzziness in this particular context
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "",
|
||||||
|
Fuzziness: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Avocado",
|
||||||
|
Fuzziness: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "Geschwindigkeit",
|
||||||
|
Fuzziness: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "non-exist",
|
||||||
|
Fuzziness: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "갃갃갃",
|
||||||
|
Fuzziness: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, scenario := range scenarios {
|
||||||
|
t.Run(fmt.Sprintf("ensure fuzziness of '%s' is '%d'", scenario.Input, scenario.Fuzziness), func(t *testing.T) {
|
||||||
|
assert.Equal(t, scenario.Fuzziness, GuessFuzzinessByKeyword(scenario.Input))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -7,11 +7,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
|
||||||
"code.gitea.io/gitea/modules/repository"
|
"code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
@ -24,25 +22,6 @@ const (
|
|||||||
GitPushOptionCount = "GIT_PUSH_OPTION_COUNT"
|
GitPushOptionCount = "GIT_PUSH_OPTION_COUNT"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GitPushOptions is a wrapper around a map[string]string
|
|
||||||
type GitPushOptions map[string]string
|
|
||||||
|
|
||||||
// GitPushOptions keys
|
|
||||||
const (
|
|
||||||
GitPushOptionRepoPrivate = "repo.private"
|
|
||||||
GitPushOptionRepoTemplate = "repo.template"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bool checks for a key in the map and parses as a boolean
|
|
||||||
func (g GitPushOptions) Bool(key string) optional.Option[bool] {
|
|
||||||
if val, ok := g[key]; ok {
|
|
||||||
if b, err := strconv.ParseBool(val); err == nil {
|
|
||||||
return optional.Some(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return optional.None[bool]()
|
|
||||||
}
|
|
||||||
|
|
||||||
// HookOptions represents the options for the Hook calls
|
// HookOptions represents the options for the Hook calls
|
||||||
type HookOptions struct {
|
type HookOptions struct {
|
||||||
OldCommitIDs []string
|
OldCommitIDs []string
|
||||||
|
45
modules/private/pushoptions.go
Normal file
45
modules/private/pushoptions.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package private
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/optional"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GitPushOptions is a wrapper around a map[string]string
|
||||||
|
type GitPushOptions map[string]string
|
||||||
|
|
||||||
|
// GitPushOptions keys
|
||||||
|
const (
|
||||||
|
GitPushOptionRepoPrivate = "repo.private"
|
||||||
|
GitPushOptionRepoTemplate = "repo.template"
|
||||||
|
GitPushOptionForcePush = "force-push"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bool checks for a key in the map and parses as a boolean
|
||||||
|
// An option without value is considered true, eg: "-o force-push" or "-o repo.private"
|
||||||
|
func (g GitPushOptions) Bool(key string) optional.Option[bool] {
|
||||||
|
if val, ok := g[key]; ok {
|
||||||
|
if val == "" {
|
||||||
|
return optional.Some(true)
|
||||||
|
}
|
||||||
|
if b, err := strconv.ParseBool(val); err == nil {
|
||||||
|
return optional.Some(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return optional.None[bool]()
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFromKeyValue adds a key value pair to the map by "key=value" format or "key" for empty value
|
||||||
|
func (g GitPushOptions) AddFromKeyValue(line string) {
|
||||||
|
kv := strings.SplitN(line, "=", 2)
|
||||||
|
if len(kv) == 2 {
|
||||||
|
g[kv[0]] = kv[1]
|
||||||
|
} else {
|
||||||
|
g[kv[0]] = ""
|
||||||
|
}
|
||||||
|
}
|
30
modules/private/pushoptions_test.go
Normal file
30
modules/private/pushoptions_test.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package private
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGitPushOptions(t *testing.T) {
|
||||||
|
o := GitPushOptions{}
|
||||||
|
|
||||||
|
v := o.Bool("no-such")
|
||||||
|
assert.False(t, v.Has())
|
||||||
|
assert.False(t, v.Value())
|
||||||
|
|
||||||
|
o.AddFromKeyValue("opt1=a=b")
|
||||||
|
o.AddFromKeyValue("opt2=false")
|
||||||
|
o.AddFromKeyValue("opt3=true")
|
||||||
|
o.AddFromKeyValue("opt4")
|
||||||
|
|
||||||
|
assert.Equal(t, "a=b", o["opt1"])
|
||||||
|
assert.False(t, o.Bool("opt1").Value())
|
||||||
|
assert.True(t, o.Bool("opt2").Has())
|
||||||
|
assert.False(t, o.Bool("opt2").Value())
|
||||||
|
assert.True(t, o.Bool("opt3").Value())
|
||||||
|
assert.True(t, o.Bool("opt4").Value())
|
||||||
|
}
|
@ -580,6 +580,8 @@ lang_select_error=Sélectionnez une langue dans la liste.
|
|||||||
|
|
||||||
username_been_taken=Le nom d'utilisateur est déjà pris.
|
username_been_taken=Le nom d'utilisateur est déjà pris.
|
||||||
username_change_not_local_user=Les utilisateurs non-locaux n'ont pas le droit de modifier leur nom d'utilisateur.
|
username_change_not_local_user=Les utilisateurs non-locaux n'ont pas le droit de modifier leur nom d'utilisateur.
|
||||||
|
change_username_disabled=Le changement de nom d’utilisateur est désactivé.
|
||||||
|
change_full_name_disabled=Le changement de nom complet est désactivé.
|
||||||
username_has_not_been_changed=Le nom d'utilisateur n'a pas été modifié
|
username_has_not_been_changed=Le nom d'utilisateur n'a pas été modifié
|
||||||
repo_name_been_taken=Ce nom de dépôt est déjà utilisé.
|
repo_name_been_taken=Ce nom de dépôt est déjà utilisé.
|
||||||
repository_force_private=Force Private est activé : les dépôts privés ne peuvent pas être rendus publics.
|
repository_force_private=Force Private est activé : les dépôts privés ne peuvent pas être rendus publics.
|
||||||
@ -1039,6 +1041,7 @@ issue_labels_helper=Sélectionner un jeu de label.
|
|||||||
license=Licence
|
license=Licence
|
||||||
license_helper=Sélectionner une licence
|
license_helper=Sélectionner une licence
|
||||||
license_helper_desc=Une licence réglemente ce que les autres peuvent ou ne peuvent pas faire avec votre code. Vous ne savez pas laquelle est la bonne pour votre projet ? Comment <a target="_blank" rel="noopener noreferrer" href="%s">choisir une licence</a>.
|
license_helper_desc=Une licence réglemente ce que les autres peuvent ou ne peuvent pas faire avec votre code. Vous ne savez pas laquelle est la bonne pour votre projet ? Comment <a target="_blank" rel="noopener noreferrer" href="%s">choisir une licence</a>.
|
||||||
|
multiple_licenses=Licences multiples
|
||||||
object_format=Format d'objet
|
object_format=Format d'objet
|
||||||
object_format_helper=Format d’objet pour ce dépôt. Ne peut être modifié plus tard. SHA1 est le plus compatible.
|
object_format_helper=Format d’objet pour ce dépôt. Ne peut être modifié plus tard. SHA1 est le plus compatible.
|
||||||
readme=LISEZMOI
|
readme=LISEZMOI
|
||||||
@ -1834,7 +1837,7 @@ pulls.is_empty=Les changements sur cette branche sont déjà sur la branche cibl
|
|||||||
pulls.required_status_check_failed=Certains contrôles requis n'ont pas réussi.
|
pulls.required_status_check_failed=Certains contrôles requis n'ont pas réussi.
|
||||||
pulls.required_status_check_missing=Certains contrôles requis sont manquants.
|
pulls.required_status_check_missing=Certains contrôles requis sont manquants.
|
||||||
pulls.required_status_check_administrator=En tant qu'administrateur, vous pouvez toujours fusionner cette requête de pull.
|
pulls.required_status_check_administrator=En tant qu'administrateur, vous pouvez toujours fusionner cette requête de pull.
|
||||||
pulls.blocked_by_approvals=Cette demande d'ajout n’est pas suffisamment approuvée. %d approbations obtenues sur %d.
|
pulls.blocked_by_approvals=Cette demande d’ajout n’est pas suffisamment approuvée. %d approbations obtenues sur %d.
|
||||||
pulls.blocked_by_approvals_whitelisted=Cette demande d’ajout n’a pas encore assez d’approbations. %d sur %d approbations de la part des utilisateurs ou équipes sur la liste autorisée.
|
pulls.blocked_by_approvals_whitelisted=Cette demande d’ajout n’a pas encore assez d’approbations. %d sur %d approbations de la part des utilisateurs ou équipes sur la liste autorisée.
|
||||||
pulls.blocked_by_rejection=Cette demande d’ajout nécessite des corrections sollicitées par un évaluateur officiel.
|
pulls.blocked_by_rejection=Cette demande d’ajout nécessite des corrections sollicitées par un évaluateur officiel.
|
||||||
pulls.blocked_by_official_review_requests=Cette demande d’ajout a des sollicitations officielles d’évaluation.
|
pulls.blocked_by_official_review_requests=Cette demande d’ajout a des sollicitations officielles d’évaluation.
|
||||||
@ -2940,6 +2943,7 @@ dashboard.start_schedule_tasks=Démarrer les tâches planifiées
|
|||||||
dashboard.sync_branch.started=Début de la synchronisation des branches
|
dashboard.sync_branch.started=Début de la synchronisation des branches
|
||||||
dashboard.sync_tag.started=Synchronisation des étiquettes
|
dashboard.sync_tag.started=Synchronisation des étiquettes
|
||||||
dashboard.rebuild_issue_indexer=Reconstruire l’indexeur des tickets
|
dashboard.rebuild_issue_indexer=Reconstruire l’indexeur des tickets
|
||||||
|
dashboard.sync_repo_licenses=Synchroniser les licences du dépôt
|
||||||
|
|
||||||
users.user_manage_panel=Gestion du compte utilisateur
|
users.user_manage_panel=Gestion du compte utilisateur
|
||||||
users.new_account=Créer un compte
|
users.new_account=Créer un compte
|
||||||
|
@ -2890,17 +2890,167 @@ dashboard.delete_generated_repository_avatars=Scrios abhatáranna stórtha ginte
|
|||||||
dashboard.sync_repo_branches=Sync brainsí caillte ó shonraí git go bunachair sonraí
|
dashboard.sync_repo_branches=Sync brainsí caillte ó shonraí git go bunachair sonraí
|
||||||
dashboard.sync_repo_tags=Clibeanna sioncraigh ó shonraí git go bunachar sonraí
|
dashboard.sync_repo_tags=Clibeanna sioncraigh ó shonraí git go bunachar sonraí
|
||||||
dashboard.update_mirrors=Scátháin a nuashonrú
|
dashboard.update_mirrors=Scátháin a nuashonrú
|
||||||
|
dashboard.repo_health_check=Seiceáil sláinte gach stóras
|
||||||
|
dashboard.check_repo_stats=Seiceáil gach staitisticí stórais
|
||||||
|
dashboard.archive_cleanup=Scrios sean-chartlanna stórais
|
||||||
|
dashboard.deleted_branches_cleanup=Brainsí scriosta a ghlanadh
|
||||||
|
dashboard.update_migration_poster_id=Nuashonraigh ID póstaer imir
|
||||||
|
dashboard.git_gc_repos=Bailíonn truflais gach stórais
|
||||||
|
dashboard.resync_all_sshkeys=Nuashonraigh an comhad '.ssh/authorized_keys' le heochracha Gitea SSH.
|
||||||
|
dashboard.resync_all_sshprincipals=Nuashonraigh an comhad '.ssh/authorized_principals' le príomhphrionsabail Gitea SSH.
|
||||||
|
dashboard.resync_all_hooks=Athshioncrónaigh crúcaí réamhfhála, nuashonraithe agus iar-fhála na stórtha go léir.
|
||||||
|
dashboard.reinit_missing_repos=Aththosaigh gach stórais Git atá in easnamh a bhfuil taifid ann dóibh
|
||||||
|
dashboard.sync_external_users=Sioncrónaigh sonraí úsáideoirí seachtracha
|
||||||
|
dashboard.cleanup_hook_task_table=Tábla hook_task glantacháin
|
||||||
|
dashboard.cleanup_packages=Pacáistí glanta in éag
|
||||||
|
dashboard.cleanup_actions=Gníomhaíochtaí glanta in éag acmhainní
|
||||||
|
dashboard.server_uptime=Aga fónaimh Freastalaí
|
||||||
|
dashboard.current_goroutine=Goroutines Reatha
|
||||||
|
dashboard.current_memory_usage=Úsáid Cuimhne Reatha
|
||||||
|
dashboard.total_memory_allocated=Cuimhne Iomlán Leithdháilte
|
||||||
|
dashboard.memory_obtained=Cuimhne Faighte
|
||||||
|
dashboard.pointer_lookup_times=Amanna Cuardaigh Pointeora
|
||||||
|
dashboard.memory_allocate_times=Leithdháiltí Cuimhne
|
||||||
|
dashboard.memory_free_times=Saorálann Cuimhne
|
||||||
|
dashboard.current_heap_usage=Úsáid Charn Reatha
|
||||||
|
dashboard.heap_memory_obtained=Cuimhne Charn Faighte
|
||||||
|
dashboard.heap_memory_idle=Díomhaoin Cuimhne Carn
|
||||||
|
dashboard.heap_memory_in_use=Cuimhne Carm In Úsáid
|
||||||
|
dashboard.heap_memory_released=Cuimhne Carn Eisithe
|
||||||
|
dashboard.heap_objects=Cuspóirí Carn
|
||||||
|
dashboard.bootstrap_stack_usage=Úsáid Staca Bootstrap
|
||||||
|
dashboard.stack_memory_obtained=Cuimhne Staca Faighte
|
||||||
|
dashboard.mspan_structures_usage=Úsáid Struchtúir MSpan
|
||||||
|
dashboard.mspan_structures_obtained=Struchtúir MSpan a Faightear
|
||||||
|
dashboard.mcache_structures_usage=Úsáid Struchtúir MCache
|
||||||
|
dashboard.mcache_structures_obtained=Struchtúir MCache a Faightear
|
||||||
|
dashboard.profiling_bucket_hash_table_obtained=Tábla Hash Buicéad Próifílithe a Faightear
|
||||||
|
dashboard.gc_metadata_obtained=Meiteashonraí GC faighte
|
||||||
|
dashboard.other_system_allocation_obtained=Leithdháileadh Córais Eile a Fuarthas
|
||||||
|
dashboard.next_gc_recycle=Athchúrsáil GC Eile
|
||||||
|
dashboard.last_gc_time=Ó Am Deiridh GC
|
||||||
|
dashboard.total_gc_time=Sos Iomlán GC
|
||||||
|
dashboard.total_gc_pause=Sos Iomlán GC
|
||||||
|
dashboard.last_gc_pause=Sos GC Deireanach
|
||||||
|
dashboard.gc_times=Amanna GC
|
||||||
|
dashboard.delete_old_actions=Scrios gach sean-ghníomhaíocht ón mbunachar
|
||||||
|
dashboard.delete_old_actions.started=Scrios na sean-ghníomhaíocht go léir ón mbunachar sonraí tosaithe.
|
||||||
|
dashboard.update_checker=Seiceoir nuashonraithe
|
||||||
|
dashboard.delete_old_system_notices=Scrios gach seanfhógra córais ón mbunachar sonraí
|
||||||
|
dashboard.gc_lfs=Bailigh truflais meta rudaí LFS
|
||||||
|
dashboard.stop_zombie_tasks=Stad gníomhartha tascanna zombie
|
||||||
|
dashboard.stop_endless_tasks=Stad gníomhartha tascanna gan deireadh
|
||||||
|
dashboard.cancel_abandoned_jobs=Cealaigh gníomhartha poist tréigthe
|
||||||
|
dashboard.start_schedule_tasks=Tosaigh tascanna sceideal gníom
|
||||||
|
dashboard.sync_branch.started=Thosaigh Brainsí Sioncronú
|
||||||
|
dashboard.sync_tag.started=Clibeanna Thosaigh Sioncronú
|
||||||
|
dashboard.rebuild_issue_indexer=Atógáil innéacsóir eisiúna
|
||||||
dashboard.sync_repo_licenses=Sioncronaigh ceadúnais repo
|
dashboard.sync_repo_licenses=Sioncronaigh ceadúnais repo
|
||||||
|
|
||||||
|
users.user_manage_panel=Bainistíocht Cuntas Úsáideora
|
||||||
|
users.new_account=Cruthaigh cuntas Úsáideora
|
||||||
|
users.name=Ainm úsáideora
|
||||||
users.full_name=Ainm Iomlán
|
users.full_name=Ainm Iomlán
|
||||||
|
users.activated=Gníomhachtaithe
|
||||||
|
users.admin=Riarachán
|
||||||
|
users.restricted=Srianta
|
||||||
|
users.reserved=In áirithe
|
||||||
|
users.bot=Bota
|
||||||
|
users.remote=Iargúlta
|
||||||
|
users.2fa=2FA
|
||||||
|
users.repos=Stórais
|
||||||
|
users.created=Cruthaithe
|
||||||
|
users.last_login=Sínigh Isteach Deiridh
|
||||||
|
users.never_login=Ná Sínigh Isteach riamh
|
||||||
|
users.send_register_notify=Seol Fógra um Chlárú Úsáideora
|
||||||
|
users.new_success=Tá an cuntas úsáideora "%s" cruthaithe.
|
||||||
|
users.edit=Eagar
|
||||||
|
users.auth_source=Foinse Fíordheimhnithe
|
||||||
|
users.local=Áitiúil
|
||||||
|
users.auth_login_name=Ainm Síniú Isteach Fíordheimhnithe
|
||||||
|
users.password_helper=Fág an pasfhocal folamh chun é a choinneáil gan athrú.
|
||||||
|
users.update_profile_success=Nuashonraíodh an cuntas úsáideora.
|
||||||
|
users.edit_account=Cuir Cuntas Úsáideora in Eagar
|
||||||
|
users.max_repo_creation=Uasmhéid Stóras
|
||||||
|
users.max_repo_creation_desc=(Cuir isteach -1 chun an teorainn réamhshocraithe domhanda a úsáid.)
|
||||||
|
users.is_activated=Gníomhachtaítear Cuntas Úsáideora
|
||||||
|
users.prohibit_login=Díchumasaigh Síniú Isteach
|
||||||
|
users.is_admin=Is Riarthóir
|
||||||
|
users.is_restricted=Is Srianta
|
||||||
|
users.allow_git_hook=Féadfaidh Git Hooks a Chruthú
|
||||||
|
users.allow_git_hook_tooltip=Déantar Git Hooks a fhorghníomhú mar úsáideoir OS a ritheann Gitea agus beidh an leibhéal céanna rochtana óstaigh aige. Mar thoradh air sin, is féidir le húsáideoirí a bhfuil an phribhléid speisialta Git Hook seo acu rochtain a fháil ar gach stór Gitea agus iad a mhodhnú chomh maith leis an mbunachar sonraí a úsáideann Gitea. Dá bharr sin tá siad in ann pribhléidí riarthóra Gitea a fháil freisin.
|
||||||
|
users.allow_import_local=Is féidir Stórais Áitiúla a Allmhairiú
|
||||||
|
users.allow_create_organization=Is féidir Eagraíochtaí a Chruthú
|
||||||
|
users.update_profile=Nuashonraigh Cuntas Úsáideora
|
||||||
|
users.delete_account=Scrios Cuntas Úsáide
|
||||||
|
users.cannot_delete_self=Ní féidir leat tú féin a scriosadh
|
||||||
|
users.still_own_repo=Tá stórais amháin nó níos mó fós ag an úsáideoir seo. Scrios nó aistrigh na stórais seo ar dtús.
|
||||||
|
users.still_has_org=Is ball d'eagraíocht é an t-úsáideoir seo. Bain an t-úsáideoir ó aon eagraíochtaí ar dtús.
|
||||||
|
users.purge=Úsáideoir a Ghlanadh
|
||||||
|
users.purge_help=Scrios go héigeantach úsáideoir agus aon stórais, eagraíochtaí agus pacáistí atá faoi úinéireacht an úsáideora. Scriosfar gach trácht freisin.
|
||||||
|
users.still_own_packages=Tá pacáiste amháin nó níos mó fós ag an úsáideoir seo, scrios na pacáistí seo ar dtús.
|
||||||
|
users.deletion_success=Scriosadh an cuntas úsáideora.
|
||||||
|
users.reset_2fa=Athshocraigh 2FA
|
||||||
|
users.list_status_filter.menu_text=Scagaire
|
||||||
|
users.list_status_filter.reset=Athshocraigh
|
||||||
users.list_status_filter.is_active=Gníomhach
|
users.list_status_filter.is_active=Gníomhach
|
||||||
|
users.list_status_filter.not_active=Neamhghníomhach
|
||||||
|
users.list_status_filter.is_admin=Riarachán
|
||||||
|
users.list_status_filter.not_admin=Ní Riarachán
|
||||||
|
users.list_status_filter.is_restricted=Srianta
|
||||||
|
users.list_status_filter.not_restricted=Gan Srian
|
||||||
|
users.list_status_filter.is_prohibit_login=Cosc ar Logáil Isteach
|
||||||
|
users.list_status_filter.not_prohibit_login=Ceadaigh Logáil isteach
|
||||||
|
users.list_status_filter.is_2fa_enabled=2FA Cumasaithe
|
||||||
|
users.list_status_filter.not_2fa_enabled=2FA faoi mhíchumas
|
||||||
|
users.details=Sonraí Úsáideora
|
||||||
|
|
||||||
|
emails.email_manage_panel=Bainistíocht Ríomhphost Úsáideoir
|
||||||
|
emails.primary=Bunscoile
|
||||||
|
emails.activated=Gníomhachtaithe
|
||||||
|
emails.filter_sort.email=Ríomhphost
|
||||||
|
emails.filter_sort.email_reverse=Ríomhphost (droim ar ais)
|
||||||
|
emails.filter_sort.name=Ainm Úsáideora
|
||||||
|
emails.filter_sort.name_reverse=Ainm Úsáideora (droim ar ais)
|
||||||
|
emails.updated=Nuashonraíodh an ríomhphost
|
||||||
|
emails.not_updated=Theip ar an seoladh ríomhphoist iarrtha a nuashonrú: %v
|
||||||
|
emails.duplicate_active=Tá an seoladh ríomhphoist seo gníomhach cheana féin d'úsáideoir difriúil.
|
||||||
|
emails.change_email_header=Nuashonraigh Airíonna Ríomhphoist
|
||||||
|
emails.change_email_text=An bhfuil tú cinnte gur mhaith leat an seoladh ríomhphoist seo a nuashonrú?
|
||||||
|
emails.delete=Scrios Ríomhphost
|
||||||
|
emails.delete_desc=An bhfuil tú cinnte gur mhaith leat an seoladh ríomhphoist seo a scriosadh?
|
||||||
|
emails.deletion_success=Tá an seoladh ríomhphoist scriosta.
|
||||||
|
emails.delete_primary_email_error=Ní féidir leat an ríomhphost príomhúil a scriosadh.
|
||||||
|
|
||||||
|
orgs.org_manage_panel=Bainistíocht Eagraíochta
|
||||||
|
orgs.name=Ainm
|
||||||
orgs.teams=Foirne
|
orgs.teams=Foirne
|
||||||
|
orgs.members=Comhaltaí
|
||||||
|
orgs.new_orga=Eagraíocht Nua
|
||||||
|
|
||||||
|
repos.repo_manage_panel=Bainistíocht Stórais
|
||||||
|
repos.unadopted=Stórais Neamhghlactha
|
||||||
|
repos.unadopted.no_more=Níor aimsíodh níos mó stórais neamhghlactha
|
||||||
repos.owner=Úinéir
|
repos.owner=Úinéir
|
||||||
|
repos.name=Ainm
|
||||||
|
repos.private=Príobháideach
|
||||||
|
repos.issues=Saincheisteanna
|
||||||
|
repos.size=Méid
|
||||||
|
repos.lfs_size=Méid LFS
|
||||||
|
|
||||||
|
packages.package_manage_panel=Bainistíocht Pacáiste
|
||||||
|
packages.total_size=Méid Iomlán: %s
|
||||||
|
packages.unreferenced_size=Méid gan tagairt: %s
|
||||||
|
packages.cleanup=Glan suas sonraí in éag
|
||||||
|
packages.cleanup.success=Glanadh suas sonraí in éag go rathúil
|
||||||
packages.owner=Úinéir
|
packages.owner=Úinéir
|
||||||
|
packages.creator=Cruthaitheoir
|
||||||
|
packages.name=Ainm
|
||||||
|
packages.version=Leagan
|
||||||
|
packages.type=Cineál
|
||||||
|
packages.repository=Stóráil
|
||||||
|
packages.size=Méid
|
||||||
|
packages.published=Foilsithe
|
||||||
|
|
||||||
defaulthooks=Réamhshocraithe Crúcaí Gréasán
|
defaulthooks=Réamhshocraithe Crúcaí Gréasán
|
||||||
defaulthooks.desc=Déanann Crúcaí Gréasán iarratais HTTP POST go huathoibríoch chuig freastalaí nuair a chuireann imeachtaí áirithe Gitea tús. Is mainneachtainí iad na cuacha gréasáin a shainítear anseo agus déanfar iad a chóipeáil isteach i ngach stórais nua. Léigh tuilleadh sa <a target="_blank" rel="noopener" href="%s">treoir chúca Crúcaí Gréasán</a>.
|
defaulthooks.desc=Déanann Crúcaí Gréasán iarratais HTTP POST go huathoibríoch chuig freastalaí nuair a chuireann imeachtaí áirithe Gitea tús. Is mainneachtainí iad na cuacha gréasáin a shainítear anseo agus déanfar iad a chóipeáil isteach i ngach stórais nua. Léigh tuilleadh sa <a target="_blank" rel="noopener" href="%s">treoir chúca Crúcaí Gréasán</a>.
|
||||||
@ -2912,60 +3062,636 @@ systemhooks.desc=Déanann Crúcaí Gréasán iarratais HTTP POST go huathoibrío
|
|||||||
systemhooks.add_webhook=Cuir Crúca Gréasán Córas leis
|
systemhooks.add_webhook=Cuir Crúca Gréasán Córas leis
|
||||||
systemhooks.update_webhook=Nuashonraigh Córas Crúca Gréasán
|
systemhooks.update_webhook=Nuashonraigh Córas Crúca Gréasán
|
||||||
|
|
||||||
|
auths.auth_manage_panel=Bainistiú Foinse Fíordheimhnithe
|
||||||
|
auths.new=Cuir Foinse Fíordheimhni
|
||||||
|
auths.name=Ainm
|
||||||
|
auths.type=Cineál
|
||||||
|
auths.enabled=Cumasaithe
|
||||||
|
auths.syncenabled=Cumasaigh Sioncrónú Úsáideora
|
||||||
auths.updated=Nuashonraithe
|
auths.updated=Nuashonraithe
|
||||||
|
auths.auth_type=Cineál Fíordheimhnithe
|
||||||
|
auths.auth_name=Ainm Fíordheimhnithe
|
||||||
|
auths.security_protocol=Prótacal Slándála
|
||||||
auths.domain=Fearann
|
auths.domain=Fearann
|
||||||
|
auths.host=Óstach
|
||||||
|
auths.port=Calafort
|
||||||
|
auths.bind_dn=Ceangail DN
|
||||||
|
auths.bind_password=Ceangail Pasfhocal
|
||||||
|
auths.user_base=Bonn Cuardaigh Úsáideora
|
||||||
|
auths.user_dn=Úsáideoir DN
|
||||||
|
auths.attribute_username=Tréith Ainm Úsáideora
|
||||||
|
auths.attribute_username_placeholder=Fág folamh chun an t-ainm úsáideora a iontráiltear i Gitea a úsáid.
|
||||||
|
auths.attribute_name=Tréith Céad Ainm
|
||||||
|
auths.attribute_surname=Tréith Sloinne
|
||||||
|
auths.attribute_mail=Tréith ríomhphoist
|
||||||
|
auths.attribute_ssh_public_key=Tréith Eochair SSH Phoiblí
|
||||||
|
auths.attribute_avatar=Tréith Avatar
|
||||||
|
auths.attributes_in_bind=Faigh tréithe i gComhthéacs Bind DN
|
||||||
|
auths.allow_deactivate_all=Lig do thoradh cuardaigh folamh gach úsáideoir a dhíghníomhachtú
|
||||||
|
auths.use_paged_search=Úsáid Cuardach Leathanaigh
|
||||||
|
auths.search_page_size=Méid an Leathanaigh
|
||||||
|
auths.filter=Scagaire Úsáideora
|
||||||
|
auths.admin_filter=Scagaire Riaracháin
|
||||||
|
auths.restricted_filter=Scagaire Srianta
|
||||||
|
auths.restricted_filter_helper=Fág folamh chun aon úsáideoirí a shocrú mar theoranta. Úsáid réiltín ('*') chun gach úsáideoir nach meaitseálann Scagaire Riaracháin a shocrú mar theoranta.
|
||||||
|
auths.verify_group_membership=Fíoraigh ballraíocht ghrúpa i LDAP (fág an scagaire folamh le scipeáil)
|
||||||
|
auths.group_search_base=Bonn Cuardaigh Grúpa DN
|
||||||
|
auths.group_attribute_list_users=Tréith Grúpa ina bhfuil Liosta Úsáideoirí
|
||||||
|
auths.user_attribute_in_group=Tréith Úsáideora atá Liostaithe i nGrúpa
|
||||||
|
auths.map_group_to_team=Léarscáil grúpaí LDAP chuig foirne na hEagraíochta (fág an réimse folamh le scipeáil)
|
||||||
|
auths.map_group_to_team_removal=Bain úsáideoirí ó fhoirne sioncronaithe mura mbaineann an t-úsáideoir leis an ngrúpa comhfhreagrach LDAP
|
||||||
|
auths.enable_ldap_groups=Cumasaigh grúpaí LDAP
|
||||||
|
auths.ms_ad_sa=MS AD Tréithe Cuardaigh
|
||||||
|
auths.smtp_auth=Cineál Fíordheimhnithe SMTP
|
||||||
|
auths.smtphost=Óstach SMTP
|
||||||
|
auths.smtpport=SMTP Calafort
|
||||||
|
auths.allowed_domains=Fearainn Ceadaithe
|
||||||
|
auths.allowed_domains_helper=Fág folamh chun gach fearann a cheadú. Déan ilfhearann a scaradh le camóg (',').
|
||||||
|
auths.skip_tls_verify=Scipeáil Fíorú TLS
|
||||||
|
auths.force_smtps=Fórsa SMTPS
|
||||||
|
auths.force_smtps_helper=Úsáidtear SMTPS i gcónaí ar chalafort 465. Socraigh é seo chun SMTPS a chur i bhfeidhm ar chalafoirt eile. (Seachas sin úsáidfear STARTTLS ar chalafoirt eile má thacaíonn an t-óstach leis.)
|
||||||
|
auths.helo_hostname=Ainm Óstach HELO
|
||||||
|
auths.helo_hostname_helper=Ainm óstach a sheoltar le HELO. Fág bán chun an t-ainm óstach reatha a sheoladh.
|
||||||
|
auths.disable_helo=Díchumasaigh HELO
|
||||||
|
auths.pam_service_name=Ainm Seirbhíse PAM
|
||||||
|
auths.pam_email_domain=Fearann Ríomhphoist PAM (roghnach)
|
||||||
|
auths.oauth2_provider=Soláthraí OAuth2
|
||||||
|
auths.oauth2_icon_url=URL deilbhín
|
||||||
|
auths.oauth2_clientID=Aitheantas Cliant (Eochair)
|
||||||
|
auths.oauth2_clientSecret=Rúnda Cliant
|
||||||
|
auths.openIdConnectAutoDiscoveryURL=URL Fionnachtana Uathoibríoch OpenID Connect
|
||||||
|
auths.oauth2_use_custom_url=Úsáid URLanna Saincheaptha in ionad URLanna Réamhshocraithe
|
||||||
|
auths.oauth2_tokenURL=URL Comhartha
|
||||||
|
auths.oauth2_authURL=Údaraigh URL
|
||||||
|
auths.oauth2_profileURL=URL Próifíl
|
||||||
|
auths.oauth2_emailURL=URL ríomhphoist
|
||||||
|
auths.skip_local_two_fa=Scipeáil 2FA áitiúil
|
||||||
|
auths.skip_local_two_fa_helper=Ciallaíonn fágáil gan socrú go mbeidh ar úsáideoirí áitiúla a bhfuil tacar 2FA acu 2FA a rith fós chun logáil isteach
|
||||||
|
auths.oauth2_tenant=Tionónta
|
||||||
|
auths.oauth2_scopes=Scóipeanna Breise
|
||||||
|
auths.oauth2_required_claim_name=Ainm Éilimh Riachtanach
|
||||||
|
auths.oauth2_required_claim_name_helper=Socraigh an t-ainm seo chun logáil isteach ón bhfoinse seo a shrianadh d'úsáideoirí a bhfuil éileamh acu leis an ainm seo
|
||||||
|
auths.oauth2_required_claim_value=Luach Éilimh Riachtanach
|
||||||
|
auths.oauth2_required_claim_value_helper=Socraigh an luach seo chun logáil isteach ón bhfoinse seo a shrianadh chuig úsáideoirí a bhfuil éileamh acu leis an ainm agus an luach seo
|
||||||
|
auths.oauth2_group_claim_name=Ainm éileamh ag soláthar ainmneacha grúpa don fhoinse seo (Roghnach)
|
||||||
|
auths.oauth2_admin_group=Luach Éilimh Grúpa d'úsáideoirí riarthóra. (Roghnach - teastaíonn ainm éilimh thuas)
|
||||||
|
auths.oauth2_restricted_group=Luach Éilimh Grúpa d'úsáideoirí srianta. (Roghnach - teastaíonn ainm éilimh thuas)
|
||||||
|
auths.oauth2_map_group_to_team=Map mhaígh grúpaí chuig foirne Eagraíochta. (Roghnach - éilíonn ainm an éilimh thuas)
|
||||||
|
auths.oauth2_map_group_to_team_removal=Bain úsáideoirí ó fhoirne sioncronaithe mura mbaineann an t-úsáideoir leis an ngrúpa comhfhreagrach.
|
||||||
|
auths.enable_auto_register=Cumasaigh Clárú Auto
|
||||||
|
auths.sspi_auto_create_users=Cruthaigh úsáideoirí go huathoibríoch
|
||||||
|
auths.sspi_auto_create_users_helper=Lig do mhodh auth SSPI cuntais nua a chruthú go huathoibríoch d'úsáideoirí a logálann isteach den chéad uair
|
||||||
|
auths.sspi_auto_activate_users=Gníomhachtaigh úsáideoirí go huathoibríoch
|
||||||
|
auths.sspi_auto_activate_users_helper=Lig modh auth SSPI úsáideoirí nua a ghníomhachtú go huathoibríoch
|
||||||
|
auths.sspi_strip_domain_names=Bain ainmneacha fearann ó ainm úsáideora
|
||||||
|
auths.sspi_strip_domain_names_helper=Má dhéantar iad a sheiceáil, bainfear ainmneacha fearainn ó ainmneacha logála isteach (m.sh. Beidh “DOMAIN\ user” agus "user@example.org" araon ní bheidh ach “úsáideoir”).
|
||||||
|
auths.sspi_separator_replacement=Deighilteoir le húsáid in ionad\,/agus @
|
||||||
|
auths.sspi_separator_replacement_helper=An carachtar a úsáidfear chun na deighilteoirí a chur in ionad na n-ainmneacha logála síos-leibhéil (m.sh. an \ i "DOMAIN\úsáideoir") agus ainmneacha príomhoidí úsáideora (m.sh. an @ in "user@example.org").
|
||||||
|
auths.sspi_default_language=Teanga úsáideora réamhshocraithe
|
||||||
|
auths.sspi_default_language_helper=Teanga réamhshocraithe d'úsáideoirí cruthaithe go huathoibríoch ag modh auth SSPI. Fág folamh más fearr leat teanga a bhrath go huathoibríoch.
|
||||||
|
auths.tips=Leideanna
|
||||||
|
auths.tips.oauth2.general=OAuth2 Fíordheimhniú
|
||||||
|
auths.tips.oauth2.general.tip=Agus fíordheimhniú OAuth2 nua á chlárú agat, ba chóir go mbeadh an URL glaonna ais/atreoraithe:
|
||||||
|
auths.tip.oauth2_provider=Soláthraí OAuth2
|
||||||
|
auths.tip.bitbucket=Cláraigh tomhaltóir OAuth nua ar %s agus cuir an cead 'Cuntas' - 'Léigh' leis
|
||||||
|
auths.tip.nextcloud=`Cláraigh tomhaltóir OAuth nua ar do chás ag baint úsáide as an roghchlár seo a leanas "Socruithe -> Slándáil -> cliant OAuth 2.0"`
|
||||||
|
auths.tip.dropbox=Cruthaigh feidhmchlár nua ag %s
|
||||||
|
auths.tip.facebook=Cláraigh feidhmchlár nua ag %s agus cuir an táirge "Facebook Login" leis
|
||||||
|
auths.tip.github=Cláraigh feidhmchlár OAuth nua ar %s
|
||||||
|
auths.tip.gitlab_new=Cláraigh feidhmchlár nua ar %s
|
||||||
|
auths.tip.google_plus=Faigh dintiúir chliaint OAuth2 ó chonsól API Google ag %s
|
||||||
|
auths.tip.openid_connect=Úsáid URL Fionnachtana OpenID Connect "https://{server}/.well-known/openid-configuration" chun na críochphointí a shonrú
|
||||||
|
auths.tip.twitter=Téigh go %s, cruthaigh feidhmchlár agus cinntigh go bhfuil an rogha "Ceadaigh úsáid a bhaint as an bhfeidhmchlár seo chun logáil isteach le Twitter" cumasaithe
|
||||||
|
auths.tip.discord=Cláraigh feidhmchlár nua ar %s
|
||||||
|
auths.tip.gitea=Cláraigh feidhmchlár OAuth2 nua. Tá treoir le fáil ag %s
|
||||||
|
auths.tip.yandex=`Cruthaigh feidhmchlár nua ag %s. Roghnaigh na ceadanna seo a leanas ón rannán "Yandex.Passport API": "Rochtain ar sheoladh ríomhphoist", "Rochtain ar avatar úsáideora" agus "Rochtain ar ainm úsáideora, céad ainm agus sloinne, inscne"`
|
||||||
|
auths.tip.mastodon=Ionchur URL sampla saincheaptha don shampla mastodon is mian leat a fhíordheimhniú leis (nó bain úsáid as an gceann réamhshocraithe)
|
||||||
|
auths.edit=Cuir Foinse Fíordheimhnithe in Eagar
|
||||||
|
auths.activated=Tá an Foinse Fíordheimhnithe seo gníomhachtaithe
|
||||||
|
auths.new_success=Tá an fíordheimhniú "%s" curtha leis.
|
||||||
|
auths.update_success=Nuashonraíodh an fhoinse fíordheimhnithe.
|
||||||
|
auths.update=Nuashonraigh Foinse Fíordheimhnithe
|
||||||
|
auths.delete=Scrios Foinse Fíordheimhnithe
|
||||||
|
auths.delete_auth_title=Scrios Foinse Fíordheimhnithe
|
||||||
|
auths.delete_auth_desc=Má scriosann tú foinse fíordheimhnithe cuirtear cosc ar úsáideoirí í a úsáid chun síniú isteach. Lean ort?
|
||||||
|
auths.still_in_used=Tá an fhoinse fíordheimhnithe fós in úsáid. Tiontaigh nó scrios aon úsáideoir a úsáideann an fhoinse fíordheimhnithe seo ar dtús.
|
||||||
|
auths.deletion_success=Tá an fhoinse fíordheimhnithe scriosta.
|
||||||
|
auths.login_source_exist=Tá an fhoinse fíordheimhnithe "%s" ann cheana.
|
||||||
|
auths.login_source_of_type_exist=Tá foinse fíordheimhnithe den chineál seo ann cheana féin.
|
||||||
|
auths.unable_to_initialize_openid=Ní féidir Soláthraí Ceangail OpenID a thionscnamh: %s
|
||||||
|
auths.invalid_openIdConnectAutoDiscoveryURL=URL Neamhbhailí Fionnachtana Uathoibríoch (ní mór gur URL bailí é seo ag tosú le http:// nó https://)
|
||||||
|
|
||||||
|
config.server_config=Cumraíocht Freastalaí
|
||||||
|
config.app_name=Teideal an Láithreáin
|
||||||
|
config.app_ver=Leagan Gitea
|
||||||
|
config.app_url=URL Bonn Gitea
|
||||||
|
config.custom_conf=Cosán Comhad Cumraíochta
|
||||||
|
config.custom_file_root_path=Cosán Fréamh Comhad Saincheaptha
|
||||||
|
config.domain=Fearann Freastalaí
|
||||||
|
config.offline_mode=Mód Áitiúil
|
||||||
|
config.disable_router_log=Díchumasaigh Loga an Ródaire
|
||||||
|
config.run_user=Rith Mar Ainm úsáideora
|
||||||
|
config.run_mode=Mód Rith
|
||||||
|
config.git_version=Leagan Git
|
||||||
|
config.app_data_path=Cosán Sonraí Aip
|
||||||
|
config.repo_root_path=Cosán Fréimhe Stórála
|
||||||
|
config.lfs_root_path=Cosán Fréamh LFS
|
||||||
|
config.log_file_root_path=Cosán Logála
|
||||||
|
config.script_type=Cineál Script
|
||||||
|
config.reverse_auth_user=Úsáideoir Fíordheimhnithe Droim ar Ais
|
||||||
|
|
||||||
|
config.ssh_config=Cumraíocht SSH
|
||||||
|
config.ssh_enabled=Cumasaithe
|
||||||
|
config.ssh_start_builtin_server=Úsáid Freastalaí Ionsuite
|
||||||
|
config.ssh_domain=Fearainn Freastalaí SSH
|
||||||
|
config.ssh_port=Calafort
|
||||||
|
config.ssh_listen_port=Éist Calafort
|
||||||
|
config.ssh_root_path=Cosán Fréimhe
|
||||||
|
config.ssh_key_test_path=Cosán Tástáil Eochair
|
||||||
|
config.ssh_keygen_path=Keygen ('ssh-keygen') Cosán
|
||||||
|
config.ssh_minimum_key_size_check=Seiceáil Íosta Méid Eochair
|
||||||
|
config.ssh_minimum_key_sizes=Méideanna Íosta Eochrach
|
||||||
|
|
||||||
|
config.lfs_config=Cumraíocht LFS
|
||||||
|
config.lfs_enabled=Cumasaithe
|
||||||
|
config.lfs_content_path=Cosán Ábhar LFS
|
||||||
|
config.lfs_http_auth_expiry=Éag Auth LFS HTTP
|
||||||
|
|
||||||
|
config.db_config=Cumraíocht Bunachar Sonraí
|
||||||
|
config.db_type=Cineál
|
||||||
|
config.db_host=Óstach
|
||||||
|
config.db_name=Ainm
|
||||||
|
config.db_user=Ainm úsáideora
|
||||||
|
config.db_schema=Scéim
|
||||||
|
config.db_ssl_mode=SSL
|
||||||
|
config.db_path=Cosán
|
||||||
|
|
||||||
|
config.service_config=Cumraíocht Seirbhíse
|
||||||
|
config.register_email_confirm=Deimhniú Ríomhphost a éileamh chun Clárú
|
||||||
|
config.disable_register=Díchumasaigh Féin-Chlárú
|
||||||
|
config.allow_only_internal_registration=Ceadaigh Clárú Amháin Trí Gitea féin
|
||||||
|
config.allow_only_external_registration=Ceadaigh Clárú Trí Sheirbhísí Seachtracha amháin
|
||||||
|
config.enable_openid_signup=Cumasaigh Féinchlárú OpenID
|
||||||
|
config.enable_openid_signin=Cumasaigh Síniú isteach OpenID
|
||||||
|
config.show_registration_button=Taispeáin Cnaipe Cláraithe
|
||||||
|
config.require_sign_in_view=Teastaíonn Sínigh isteach chun Leathanaigh Amharc
|
||||||
|
config.mail_notify=Cumasaigh Fógraí Ríomhphoist
|
||||||
|
config.enable_captcha=Cumasaigh CAPTCHA
|
||||||
|
config.active_code_lives=Saol Gníomhach ag an gCód
|
||||||
|
config.reset_password_code_lives=Am Éaga Chóid Aisghabhála Cuntais
|
||||||
|
config.default_keep_email_private=Folaigh Seoltaí Ríomhphoist de réir Réamhshocrú
|
||||||
|
config.default_allow_create_organization=Ceadaigh Cruthú Eagraíochtaí de réir Réamhshocrú
|
||||||
|
config.enable_timetracking=Cumasaigh Rianú Ama
|
||||||
|
config.default_enable_timetracking=Cumasaigh Rianú Ama de réir Réamhshocrú
|
||||||
|
config.default_allow_only_contributors_to_track_time=Lig do Rannpháirtithe Amháin Rianú Am
|
||||||
|
config.no_reply_address=Fearann Ríomhphoist Folaithe
|
||||||
|
config.default_visibility_organization=Infheictheacht réamhshocraithe d'Eagraíochtaí nua
|
||||||
|
config.default_enable_dependencies=Cumasaigh Spleáchais Eisithe de réir Réamhshocrú
|
||||||
|
|
||||||
config.webhook_config=Cumraíocht Crúca Gréasán
|
config.webhook_config=Cumraíocht Crúca Gréasán
|
||||||
|
config.queue_length=Fad scuaine
|
||||||
|
config.deliver_timeout=Teorainn Ama Seachadta
|
||||||
|
config.skip_tls_verify=Scipeáil Fíorú TLS
|
||||||
|
|
||||||
|
config.mailer_config=Cumraíocht Seoltóra
|
||||||
|
config.mailer_enabled=Cumasaithe
|
||||||
|
config.mailer_enable_helo=Cumasaigh HELO
|
||||||
|
config.mailer_name=Ainm
|
||||||
|
config.mailer_protocol=Prótacal
|
||||||
|
config.mailer_smtp_addr=Seoladh SMTP
|
||||||
|
config.mailer_smtp_port=Calafort SMTP
|
||||||
|
config.mailer_user=Úsáideoir
|
||||||
|
config.mailer_use_sendmail=Úsáid Sendmail
|
||||||
|
config.mailer_sendmail_path=Cosán Sendmail
|
||||||
|
config.mailer_sendmail_args=Argóintí Breise chuig Sendmail
|
||||||
|
config.mailer_sendmail_timeout=Teorainn Ama Sendmail
|
||||||
|
config.mailer_use_dummy=Caochadán
|
||||||
|
config.test_email_placeholder=Ríomhphost (m.sh. test@example.com)
|
||||||
|
config.send_test_mail=Seol Ríomhphost Tástála
|
||||||
|
config.send_test_mail_submit=Seol
|
||||||
|
config.test_mail_failed=Theip ar ríomhphost tástála a sheoladh chuig "%s": %v
|
||||||
|
config.test_mail_sent=Tá ríomhphost tástála seolta chuig "%s".
|
||||||
|
|
||||||
|
config.oauth_config=Cumraíocht OAuth
|
||||||
|
config.oauth_enabled=Cumasaithe
|
||||||
|
|
||||||
|
config.cache_config=Cumraíocht taisce
|
||||||
|
config.cache_adapter=Cuibheoir taisce
|
||||||
|
config.cache_interval=Eatramh Taisce
|
||||||
|
config.cache_conn=Ceangal Taisce
|
||||||
|
config.cache_item_ttl=Mír Taisce TTL
|
||||||
|
config.cache_test=Taisce Tástáil
|
||||||
|
config.cache_test_failed=Theip ar an taisce a thaiscéaladh: %v.
|
||||||
|
config.cache_test_slow=D'éirigh leis an tástáil taisce, ach tá an freagra mall: %s.
|
||||||
|
config.cache_test_succeeded=D'éirigh leis an tástáil taisce, fuair sé freagra i %s.
|
||||||
|
|
||||||
|
config.session_config=Cumraíocht Seisiúin
|
||||||
|
config.session_provider=Soláthraí Seisiúin
|
||||||
|
config.provider_config=Cumraíocht Soláthraí
|
||||||
|
config.cookie_name=Ainm Fianán
|
||||||
|
config.gc_interval_time=Am Eatramh GC
|
||||||
|
config.session_life_time=Am Saoil na Seisiúin
|
||||||
|
config.https_only=HTTPS Amháin
|
||||||
|
config.cookie_life_time=Am Saoil Fianán
|
||||||
|
|
||||||
|
config.picture_config=Cumraíocht Pictiúr agus Avatar
|
||||||
|
config.picture_service=Seirbhís Pictiúr
|
||||||
|
config.disable_gravatar=Díchumasaigh Gravatar
|
||||||
|
config.enable_federated_avatar=Cumasaigh Avatars Cónaidhme
|
||||||
|
config.open_with_editor_app_help=Na heagarthóirí "Oscailte le" don roghchlár Clón. Má fhágtar folamh é, úsáidfear an réamhshocrú. Leathnaigh chun an réamhshocrú a fheiceáil.
|
||||||
|
|
||||||
|
config.git_config=Cumraíocht Git
|
||||||
|
config.git_disable_diff_highlight=Díchumasaigh Aibhsiú Comhréire Diff
|
||||||
|
config.git_max_diff_lines=Max Diff Lines (do chomhad amháin)
|
||||||
|
config.git_max_diff_line_characters=Carachtair Max Diff (le haghaidh líne amháin)
|
||||||
|
config.git_max_diff_files=Comhaid Max Diff (le taispeáint)
|
||||||
|
config.git_gc_args=Argóintí GC
|
||||||
|
config.git_migrate_timeout=Teorainn Ama Imirce
|
||||||
|
config.git_mirror_timeout=Teorainn Ama Nuashonraithe Scátháin
|
||||||
|
config.git_clone_timeout=Teorainn Ama Oibríochta Clón
|
||||||
|
config.git_pull_timeout=Tarraing Am Oibríochta
|
||||||
|
config.git_gc_timeout=Teorainn Ama Oibriúcháin GC
|
||||||
|
|
||||||
|
config.log_config=Cumraíocht Logáil
|
||||||
|
config.logger_name_fmt=Logálaí: %s
|
||||||
|
config.disabled_logger=Díchumasaithe
|
||||||
|
config.access_log_mode=Mód Logáil Rochtana
|
||||||
|
config.access_log_template=Teimpléad Logáil Rochtana
|
||||||
|
config.xorm_log_sql=Logáil SQL
|
||||||
|
|
||||||
|
config.set_setting_failed=Theip ar shocrú %s a shocrú
|
||||||
|
|
||||||
|
monitor.stats=Staitisticí
|
||||||
|
|
||||||
|
monitor.cron=Tascanna Cron
|
||||||
|
monitor.name=Ainm
|
||||||
|
monitor.schedule=Sceideal
|
||||||
|
monitor.next=An chéad uair eile
|
||||||
|
monitor.previous=Am Roimhe Seo
|
||||||
|
monitor.execute_times=Forghníomhaíochtaí
|
||||||
|
monitor.process=Próisis reatha
|
||||||
|
monitor.stacktrace=Rian cruachta
|
||||||
|
monitor.processes_count=Próisis %d
|
||||||
|
monitor.download_diagnosis_report=Íoslódáil tuairisc diagnóis
|
||||||
monitor.desc=Cur síos
|
monitor.desc=Cur síos
|
||||||
|
monitor.start=Am Tosaigh
|
||||||
|
monitor.execute_time=Am Forghníomhaithe
|
||||||
|
monitor.last_execution_result=Toradh
|
||||||
|
monitor.process.cancel=Cealaigh próiseas
|
||||||
|
monitor.process.cancel_desc=Má chuirtear próiseas ar ceal d'fhéadfadh go gcaillfí sonraí
|
||||||
|
monitor.process.cancel_notices=Cealaigh: <strong>%s</strong>?
|
||||||
|
monitor.process.children=Leanaí
|
||||||
|
|
||||||
|
monitor.queues=Scuaineanna
|
||||||
|
monitor.queue=Scuaine: %s
|
||||||
|
monitor.queue.name=Ainm
|
||||||
|
monitor.queue.type=Cineál
|
||||||
|
monitor.queue.exemplar=Cineál Eiseamláire
|
||||||
|
monitor.queue.numberworkers=Líon na nOibrithe
|
||||||
|
monitor.queue.activeworkers=Oibrithe Gníomhacha
|
||||||
|
monitor.queue.maxnumberworkers=Líon Uasta na nOibrithe
|
||||||
|
monitor.queue.numberinqueue=Uimhir i scuaine
|
||||||
|
monitor.queue.review_add=Athbhreithniú / Cuir Oibrithe leis
|
||||||
|
monitor.queue.settings.title=Socruithe Linn
|
||||||
|
monitor.queue.settings.desc=Fásann linnte go dinimiciúil mar fhreagra ar a gcuid scuaine oibrithe a bhlocáil.
|
||||||
|
monitor.queue.settings.maxnumberworkers=Uaslíon na n-oibrithe
|
||||||
|
monitor.queue.settings.maxnumberworkers.placeholder=Faoi láthair %[1]d
|
||||||
|
monitor.queue.settings.maxnumberworkers.error=Caithfidh uaslíon na n-oibrithe a bheith ina uimhir
|
||||||
monitor.queue.settings.submit=Nuashonrú Socruithe
|
monitor.queue.settings.submit=Nuashonrú Socruithe
|
||||||
|
monitor.queue.settings.changed=Socruithe Nuashonraithe
|
||||||
|
monitor.queue.settings.remove_all_items=Bain gach
|
||||||
|
monitor.queue.settings.remove_all_items_done=Baineadh na míreanna go léir sa scuaine.
|
||||||
|
|
||||||
notices.system_notice_list=Fógraí Córais
|
notices.system_notice_list=Fógraí Córais
|
||||||
|
notices.view_detail_header=Féach ar Sonraí Fógra
|
||||||
notices.operations=Oibríochtaí
|
notices.operations=Oibríochtaí
|
||||||
|
notices.select_all=Roghnaigh Gach
|
||||||
|
notices.deselect_all=Díroghnaigh Gach
|
||||||
|
notices.inverse_selection=Roghnú Inbhéartha
|
||||||
|
notices.delete_selected=Scrios Roghnaithe
|
||||||
|
notices.delete_all=Scrios Gach Fógra
|
||||||
|
notices.type=Cineál
|
||||||
|
notices.type_1=Stóras
|
||||||
|
notices.type_2=Tasc
|
||||||
notices.desc=Cur síos
|
notices.desc=Cur síos
|
||||||
|
notices.op=Oibríocht.
|
||||||
|
notices.delete_success=Scriosadh na fógraí córais.
|
||||||
|
|
||||||
|
self_check.no_problem_found=Níor aimsíodh aon fhadhb fós.
|
||||||
|
self_check.startup_warnings=Rabhadh tosaithe:
|
||||||
|
self_check.database_collation_mismatch=Bí ag súil le comhthiomsú a úsáid sa bhunachar sonraí: %s
|
||||||
|
self_check.database_collation_case_insensitive=Tá bunachar sonraí ag baint úsáide as comparáid %s, arb é comhdhlúthú neamhíogair. Cé go bhféadfadh Gitea oibriú leis, d'fhéadfadh go mbeadh roinnt cásanna annamh ann nach n-oibríonn mar a bhíothas ag súil leis.
|
||||||
|
self_check.database_inconsistent_collation_columns=Tá comhthiomsú %s in úsáid ag an mbunachar sonraí, ach tá comhthiomsuithe mímheaitseála á n-úsáid ag na colúin seo. D'fhéadfadh sé a bheith ina chúis le roinnt fadhbanna gan choinne.
|
||||||
|
self_check.database_fix_mysql=D'úsáideoirí MySQL/MariaDB, d'fhéadfá an t-ordú "gitea doctor convert" a úsáid chun na fadhbanna comhthiomsaithe a réiteach, nó d'fhéadfá an fhadhb a réiteach trí "ALTER ... COLLATE ..." SQLs de láimh freisin.
|
||||||
|
self_check.database_fix_mssql=I gcás úsáideoirí MSSQL, ní fhéadfá an fhadhb a réiteach ach trí "ALTER ... COLLATE ..." SQLs de láimh faoi láthair.
|
||||||
|
self_check.location_origin_mismatch=Ní mheaitseálann an URL reatha (%[1]s) an URL atá le feiceáil ag Gitea (%[2]s). Má tá seachfhreastalaí droim ar ais á úsáid agat, cinntigh le do thoil go bhfuil na ceanntásca "Óstríomhaire" agus "X-Forwarded-Proto" socraithe i gceart.
|
||||||
|
|
||||||
[action]
|
[action]
|
||||||
|
create_repo=stóras cruthaithe <a href="%s">%s</a>
|
||||||
|
rename_repo=stóras athainmnithe ó <code>%[1]s</code> go <a href="%[2]s">%[3]s</a>
|
||||||
|
commit_repo=brú chuig <a href="%[2]s">%[3]s</a> ag <a href="%[1]s">%[4]s</a>
|
||||||
|
create_issue=`osclaíodh ceist <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
close_issue=`eagrán dúnta <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
reopen_issue=`athoscailt an cheist <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
create_pull_request=`iarratas tarraingthe cruthaithe <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
close_pull_request=`iarratas tarraingthe dúnta <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
reopen_pull_request=`iarratas tarraingthe athoscailte <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
comment_issue=`trácht ar cheist <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
comment_pull=`déan trácht ar iarratas tarraingthe <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
merge_pull_request=`iarratas tarraingthe cumaisc <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
auto_merge_pull_request=`iarratas tarraingthe cumasctha go huathoibríoch <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
transfer_repo=aistrithe stóras <code>%s</code> go <a href="%s">%s</a>
|
||||||
|
push_tag=brú <a href="%[2]s">%[3]s</a> go <a href="%[1]s">%[4]s</a>
|
||||||
|
delete_tag=scriosta clib %[2]s ó <a href="%[1]s">%[3]s</a>
|
||||||
|
delete_branch=brainse scriosta %[2]s ó <a href="%[1]s">%[3]s</a>
|
||||||
|
compare_branch=Déan comparáid
|
||||||
|
compare_commits=Déan comparáid idir tiomáintí %d
|
||||||
|
compare_commits_general=Déan comparáid idir tiomáintí
|
||||||
|
mirror_sync_push=geallann synced do <a href="%[2]s">%[3]s</a> ag <a href="%[1]s">%[4]s</a> ón scáthán
|
||||||
|
mirror_sync_create=sioncronaigh tagairt nua <a href="%[2]s">%[3]s</a> do <a href="%[1]s">%[4]s</a> ón scáthán
|
||||||
|
mirror_sync_delete=sioncronaithe agus scriosta an tagairt <code>%[2]s</code> ag <a href="%[1]s">%[3]s</a> ón scáthán
|
||||||
|
approve_pull_request=`ceadaithe <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
reject_pull_request=`athruithe molta le haghaidh <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
publish_release=`scaoileadh <a href="%[2]s">%[4]s</a> ag <a href="%[1]s">%[3]s</a>`
|
||||||
|
review_dismissed=`léirmheas ó <b>%[4]s</b> le haghaidh <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
|
review_dismissed_reason=Cúis:
|
||||||
|
create_branch=brainse cruthaithe <a href="%[2]s">%[3]s</a> i <a href="%[1]s">%[4]s</a>
|
||||||
|
starred_repo=le <a href="%[1]s">%[2]s</a> le réalta
|
||||||
|
watched_repo=thosaigh sé ag breathnú ar <a href="%[1]s">%[2]s</a>
|
||||||
|
|
||||||
[tool]
|
[tool]
|
||||||
|
now=anois
|
||||||
|
future=todhchaí
|
||||||
|
1s=1 soicind
|
||||||
|
1m=1 nóiméad
|
||||||
|
1h=1 uair an chloig
|
||||||
|
1d=1 lá
|
||||||
|
1w=1 seachtain
|
||||||
|
1mon=1 mhí
|
||||||
|
1y=1 bhliain
|
||||||
|
seconds=%d soicind
|
||||||
|
minutes=%d nóiméad
|
||||||
|
hours=%d uair an chloig
|
||||||
|
days=%d laethanta
|
||||||
|
weeks=%d seachtain
|
||||||
|
months=%d míonna
|
||||||
|
years=%d bliain
|
||||||
|
raw_seconds=soicind
|
||||||
|
raw_minutes=nóiméad
|
||||||
|
|
||||||
[dropzone]
|
[dropzone]
|
||||||
|
default_message=Scaoil comhaid nó cliceáil anseo chun iad a uaslódáil.
|
||||||
|
invalid_input_type=Ní féidir leat comhaid den chineál seo a uaslódáil.
|
||||||
|
file_too_big=Sáraíonn méid comhaid ({{filesize}} MB) an t-uasmhéid de ({{maxFilesize}} MB).
|
||||||
|
remove_file=Bain an comhad
|
||||||
|
|
||||||
[notification]
|
[notification]
|
||||||
|
notifications=Fógraí
|
||||||
|
unread=Gan léamh
|
||||||
|
read=Léigh
|
||||||
|
no_unread=Gan aon fhógraí neamh-léite.
|
||||||
|
no_read=Gan aon fhógraí léite.
|
||||||
|
pin=Fógra bioráin
|
||||||
|
mark_as_read=Marcáil mar léite
|
||||||
|
mark_as_unread=Marcáil mar neamh-léite
|
||||||
|
mark_all_as_read=Marcáil gach ceann mar léite
|
||||||
|
subscriptions=Síntiúis
|
||||||
|
watching=Ag féachaint
|
||||||
|
no_subscriptions=Gan síntiúis
|
||||||
|
|
||||||
[gpg]
|
[gpg]
|
||||||
|
default_key=Sínithe leis an eochair réamhshocraithe
|
||||||
|
error.extract_sign=Theip ar an síniú a bhaint
|
||||||
|
error.generate_hash=Theip ar hash gealltanas a ghiniúint
|
||||||
|
error.no_committer_account=Níl aon chuntas nasctha le seoladh ríomhphoist an tiomnóra
|
||||||
|
error.no_gpg_keys_found=Níor aimsíodh aon eochair aithne don síniú seo sa bhunachar
|
||||||
|
error.not_signed_commit=Ní tiomantas sínithe
|
||||||
|
error.failed_retrieval_gpg_keys=Theip ar aisghabháil eochair ar bith a bhí ceangailte le cuntas an tiomnóra
|
||||||
|
error.probable_bad_signature=RABHADH! Cé go bhfuil eochair leis an ID seo sa bhunachar sonraí ní fhíoraíonn sé an tiomantas seo! Tá an tiomantas seo AMHRASACH.
|
||||||
|
error.probable_bad_default_signature=RABHADH! Cé go bhfuil an t-aitheantas seo ag an eochair réamhshocraithe ní fíoraíonn sé an tiomantas seo! Tá an tiomantas seo AMHRASACH.
|
||||||
|
|
||||||
[units]
|
[units]
|
||||||
|
unit=Aonad
|
||||||
|
error.no_unit_allowed_repo=Níl cead agat rochtain a fháil ar aon chuid den tiomantas seo.
|
||||||
|
error.unit_not_allowed=Níl cead agat an rannán stóras seo a rochtain.
|
||||||
|
|
||||||
[packages]
|
[packages]
|
||||||
|
title=Pacáistí
|
||||||
|
desc=Bainistigh pacáistí stórais.
|
||||||
|
empty=Níl aon phacáistí ann fós.
|
||||||
|
no_metadata=Gan aon mheiteashonraí.
|
||||||
|
empty.documentation=Le haghaidh tuilleadh eolais ar chlárlann na bpacáistí, féach ar <a target="_blank" rel="noopener noreferrer" href="%s">na doiciméid</a>.
|
||||||
|
empty.repo=An ndearna tú uaslódáil ar phacáiste, ach nach bhfuil sé léirithe anseo? Téigh go <a href="%[1]s">socruithe pacáiste</a> agus nasc leis an stóras seo é.
|
||||||
|
registry.documentation=Le haghaidh tuilleadh eolais ar chlárlann %s, féach ar <a target="_blank" rel="noopener noreferrer" href="%s">na doiciméid</a>.
|
||||||
|
filter.type=Cineál
|
||||||
|
filter.type.all=Gach
|
||||||
|
filter.no_result=Níor thug do scagaire aon torthaí.
|
||||||
|
filter.container.tagged=Clibeáilte
|
||||||
|
filter.container.untagged=Gan chlib
|
||||||
|
published_by=Foilsithe %[1]s ag <a href="%[2]s">%[3]s</a>
|
||||||
|
published_by_in=Foilsithe ag %[1]s ag <a href="%[2]s">%[3]s</a> in <a href="%[4]s"><strong>%[5]s</strong></a>
|
||||||
|
installation=Suiteáil
|
||||||
|
about=Maidir leis an bpacáiste seo
|
||||||
|
requirements=Riachtanais
|
||||||
|
dependencies=Spleithiúlachtaí
|
||||||
|
keywords=Eochairfhocail
|
||||||
|
details=Sonraí
|
||||||
|
details.author=Údar
|
||||||
|
details.project_site=Suíomh an Tionscadail
|
||||||
|
details.repository_site=Suíomh Stóras
|
||||||
|
details.documentation_site=Suíomh Doiciméadaithe
|
||||||
|
details.license=Ceadúnas
|
||||||
|
assets=Sócmhainní
|
||||||
|
versions=Leaganacha
|
||||||
|
versions.view_all=Féach ar gach
|
||||||
|
dependency.id=ID
|
||||||
|
dependency.version=Leagan
|
||||||
|
alpine.registry=Socraigh an chlár seo tríd an url a chur i do chomhad <code>/etc/apk/repositories</code>:
|
||||||
|
alpine.registry.key=Íoslódáil eochair RSA poiblí na clárlainne isteach san fhillteán <code>/etc/apk/keys/</code> chun an síniú innéacs a fhíorú:
|
||||||
|
alpine.registry.info=Roghnaigh $branch agus $repository ón liosta thíos.
|
||||||
|
alpine.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas:
|
||||||
|
alpine.repository=Eolas Stórais
|
||||||
alpine.repository.branches=Brainsí
|
alpine.repository.branches=Brainsí
|
||||||
alpine.repository.repositories=Stórais
|
alpine.repository.repositories=Stórais
|
||||||
|
alpine.repository.architectures=Ailtireachtaí
|
||||||
|
cargo.registry=Socraigh an clárlann seo sa chomhad cumraíochta lasta (mar shampla <code>~/.cargo/config.toml</code>):
|
||||||
|
cargo.install=Chun an pacáiste a shuiteáil ag baint úsáide as Cargo, reáchtáil an t-ordú seo a leanas:
|
||||||
|
chef.registry=Socraigh an clárlann seo i do chomhad <code>~/.chef/config.rb</code>:
|
||||||
|
chef.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas:
|
||||||
|
composer.registry=Socraigh an chlár seo i do chomhad <code>~/.composer/config.json</code>:
|
||||||
|
composer.install=Chun an pacáiste a shuiteáil ag baint úsáide as Cumadóir, reáchtáil an t-ordú seo a leanas:
|
||||||
|
composer.dependencies=Spleithiúlachtaí
|
||||||
|
composer.dependencies.development=Spleithiúlachtaí Forbartha
|
||||||
|
conan.details.repository=Stóras
|
||||||
|
conan.registry=Socraigh an clárlann seo ón líne ordaithe:
|
||||||
|
conan.install=Chun an pacáiste a shuiteáil ag úsáid Conan, reáchtáil an t-ordú seo a leanas:
|
||||||
|
conda.registry=Socraigh an chlár seo mar stóras Conda i do chomhad <code>.condarc</code>:
|
||||||
|
conda.install=Chun an pacáiste a shuiteáil ag úsáid Conda, reáchtáil an t-ordú seo a leanas:
|
||||||
|
container.details.type=Cineál Íomhá
|
||||||
|
container.details.platform=Ardán
|
||||||
|
container.pull=Tarraing an íomhá ón líne ordaithe:
|
||||||
|
container.digest=Díleáigh:
|
||||||
|
container.multi_arch=Córas Oibriúcháin / Ailtireacht
|
||||||
|
container.layers=Sraitheanna Íomhá
|
||||||
|
container.labels=Lipéid
|
||||||
|
container.labels.key=Eochair
|
||||||
|
container.labels.value=Luach
|
||||||
|
cran.registry=Cumraigh an chlárlann seo i do chomhad <code>Rprofile.site</code>:
|
||||||
|
cran.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas:
|
||||||
|
debian.registry=Socraigh an clárlann seo ón líne ordaithe:
|
||||||
|
debian.registry.info=Roghnaigh $distribution agus $component ón liosta thíos.
|
||||||
|
debian.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas:
|
||||||
|
debian.repository=Eolas Stóras
|
||||||
|
debian.repository.distributions=Dáiltí
|
||||||
|
debian.repository.components=Comhpháirteanna
|
||||||
|
debian.repository.architectures=Ailtireachtaí
|
||||||
|
generic.download=Íoslódáil pacáiste ón líne ordaithe:
|
||||||
|
go.install=Suiteáil an pacáiste ón líne ordaithe:
|
||||||
|
helm.registry=Socraigh an clárlann seo ón líne ordaithe:
|
||||||
|
helm.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas:
|
||||||
|
maven.registry=Socraigh an clárlann seo i do chomhad <code>pom.xml</code> tionscadail:
|
||||||
|
maven.install=Chun an pacáiste a úsáid cuir na nithe seo a leanas sa bhloc <code>spleáchais</code> sa chomhad <code>pom.xml</code>:
|
||||||
|
maven.install2=Rith tríd an líne ordaithe:
|
||||||
|
maven.download=Chun an spleáchas a íoslódáil, rith tríd an líne ordaithe:
|
||||||
|
nuget.registry=Socraigh an clárlann seo ón líne ordaithe:
|
||||||
|
nuget.install=Chun an pacáiste a shuiteáil ag úsáid NuGet, reáchtáil an t-ordú seo a leanas:
|
||||||
|
nuget.dependency.framework=Spriocchreat
|
||||||
|
npm.registry=Socraigh an chlárlann seo i do chomhad <code>.npmrc</code> do thionscadail:
|
||||||
|
npm.install=Chun an pacáiste a shuiteáil ag úsáid npm, reáchtáil an t-ordú seo a leanas:
|
||||||
|
npm.install2=nó cuir leis an gcomhad package.json é:
|
||||||
|
npm.dependencies=Spleithiúlachtaí
|
||||||
|
npm.dependencies.development=Spleithiúlachtaí Forbartha
|
||||||
|
npm.dependencies.bundle=Spleáchais Chuachta
|
||||||
|
npm.dependencies.peer=Spleithiúlachtaí Piaraí
|
||||||
|
npm.dependencies.optional=Spleáchais Roghnacha
|
||||||
|
npm.details.tag=Clib
|
||||||
|
pub.install=Chun an pacáiste a shuiteáil ag úsáid Dart, reáchtáil an t-ordú seo a leanas:
|
||||||
|
pypi.requires=Teastaíonn Python
|
||||||
|
pypi.install=Chun an pacáiste a shuiteáil ag úsáid pip, reáchtáil an t-ordú seo a leanas:
|
||||||
|
rpm.registry=Socraigh an clárlann seo ón líne ordaithe:
|
||||||
|
rpm.distros.redhat=ar dháileadh bunaithe ar RedHat
|
||||||
|
rpm.distros.suse=ar dháileadh bunaithe ar SUSE
|
||||||
|
rpm.install=Chun an pacáiste a shuiteáil, rith an t-ordú seo a leanas:
|
||||||
|
rpm.repository=Eolas Stóras
|
||||||
|
rpm.repository.architectures=Ailtireachtaí
|
||||||
|
rpm.repository.multiple_groups=Tá an pacáiste seo ar fáil i ngrúpaí éagsúla.
|
||||||
|
rubygems.install=Chun an pacáiste a shuiteáil ag baint úsáide as gem, reáchtáil an t-ordú seo a leanas:
|
||||||
|
rubygems.install2=nó cuir leis an Gemfile é:
|
||||||
|
rubygems.dependencies.runtime=Spleáchais Rith-Ama
|
||||||
|
rubygems.dependencies.development=Spleáchais Forbartha
|
||||||
|
rubygems.required.ruby=Éilíonn leagan Ruby
|
||||||
|
rubygems.required.rubygems=Éilíonn leagan RubyGem
|
||||||
|
swift.registry=Socraigh an clárlann seo ón líne ordaithe:
|
||||||
|
swift.install=Cuir an pacáiste i do <code>chomhad Package.swift</code>:
|
||||||
|
swift.install2=agus reáchtáil an t-ordú seo a leanas:
|
||||||
|
vagrant.install=Chun bosca Vagrant a chur leis, reáchtáil an t-ordú seo a leanas:
|
||||||
|
settings.link=Nasc an pacáiste seo le stóras
|
||||||
|
settings.link.description=Má nascann tú pacáiste le stóras, liostaítear an pacáiste i liosta pacáistí an stórais.
|
||||||
|
settings.link.select=Roghnaigh Stóras
|
||||||
|
settings.link.button=Nuashonraigh Nasc Stórais
|
||||||
|
settings.link.success=D'éirigh le nasc an stórais a nuashonrú.
|
||||||
|
settings.link.error=Theip ar an nasc stóras a nuashonrú.
|
||||||
|
settings.delete=Scrios pacáiste
|
||||||
|
settings.delete.description=Tá pacáiste a scriosadh buan agus ní féidir é a chur ar ais.
|
||||||
|
settings.delete.notice=Tá tú ar tí %s (%s) a scriosadh. Tá an oibríocht seo dochúlaithe, an bhfuil tú cinnte?
|
||||||
|
settings.delete.success=Tá an pacáiste scriosta.
|
||||||
|
settings.delete.error=Theip ar an pacáiste a scriosadh.
|
||||||
|
owner.settings.cargo.title=Innéacs Clárlann Lasta
|
||||||
|
owner.settings.cargo.initialize=Innéacs a chur i dtosach
|
||||||
|
owner.settings.cargo.initialize.description=Tá gá le stóras innéacs speisialta Git chun an clárlann Cargo a úsáid. Tríd an rogha seo, cruthófar an stóras (nó athchruthófar é) agus cumrófar é go huathoibríoch.
|
||||||
|
owner.settings.cargo.initialize.error=Níorbh fhéidir an t-innéacs Cargo a thúsú: %v
|
||||||
|
owner.settings.cargo.initialize.success=Cruthaíodh an t-innéacs Cargo go rathúil.
|
||||||
|
owner.settings.cargo.rebuild=Innéacs Atógáil
|
||||||
|
owner.settings.cargo.rebuild.description=Is féidir atógáil a bheith úsáideach mura bhfuil an t-innéacs sioncronaithe leis na pacáistí Cargo stóráilte.
|
||||||
|
owner.settings.cargo.rebuild.error=Níorbh fhéidir an t-innéacs Cargo a atógáil: %v
|
||||||
|
owner.settings.cargo.rebuild.success=D'éirigh leis an innéacs Cargo a atógáil.
|
||||||
|
owner.settings.cleanuprules.title=Bainistigh Rialacha Glanta
|
||||||
|
owner.settings.cleanuprules.add=Cuir Riail Glantacháin leis
|
||||||
|
owner.settings.cleanuprules.edit=Cuir Riail Glantacháin in eagar
|
||||||
|
owner.settings.cleanuprules.none=Níl aon rialacha glanta ar fáil. Féach ar na doiciméid le do thoil.
|
||||||
|
owner.settings.cleanuprules.preview=Réamhamharc Riail Glantacháin
|
||||||
|
owner.settings.cleanuprules.preview.overview=Tá pacáistí %d beartaithe a bhaint.
|
||||||
|
owner.settings.cleanuprules.preview.none=Ní hionann riail glantacháin agus pacáistí ar bith.
|
||||||
|
owner.settings.cleanuprules.enabled=Cumasaithe
|
||||||
|
owner.settings.cleanuprules.pattern_full_match=Cuir patrún i bhfeidhm ar ainm an phacáiste iomlán
|
||||||
|
owner.settings.cleanuprules.keep.title=Coinnítear leaganacha a mheaitseálann leis na rialacha seo, fiú má mheaitseálann siad riail bhaint thíos.
|
||||||
|
owner.settings.cleanuprules.keep.count=Coinnigh an ceann is déanaí
|
||||||
|
owner.settings.cleanuprules.keep.count.1=1 leagan in aghaidh an phacáiste
|
||||||
|
owner.settings.cleanuprules.keep.count.n=Leaganacha %d in aghaidh an phacáiste
|
||||||
|
owner.settings.cleanuprules.keep.pattern=Coinnigh leaganacha meaitseála
|
||||||
|
owner.settings.cleanuprules.keep.pattern.container=Coinnítear an leagan <code>is déanaí</code> le haghaidh pacáistí Coimeádán i gcónaí.
|
||||||
|
owner.settings.cleanuprules.remove.title=Baintear leaganacha a mheaitseálann leis na rialacha seo, mura deir riail thuas iad a choinneáil.
|
||||||
|
owner.settings.cleanuprules.remove.days=Bain leaganacha níos sine ná
|
||||||
|
owner.settings.cleanuprules.remove.pattern=Bain leaganacha meaitseála
|
||||||
|
owner.settings.cleanuprules.success.update=Nuashonraíodh an riail ghlantacháin.
|
||||||
|
owner.settings.cleanuprules.success.delete=Scriosadh an riail glantacháin.
|
||||||
|
owner.settings.chef.title=Clárlann Chef
|
||||||
|
owner.settings.chef.keypair=Gin péire eochair
|
||||||
|
owner.settings.chef.keypair.description=Tá eochairphéire riachtanach le fíordheimhniú a dhéanamh ar chlárlann an Chef. Má tá péire eochrach ginte agat roimhe seo, má ghinfidh tú eochairphéire nua, scriosfar an seanphéire eochair.
|
||||||
|
|
||||||
[secrets]
|
[secrets]
|
||||||
|
secrets=Rúin
|
||||||
|
description=Cuirfear rúin ar aghaidh chuig gníomhartha áirithe agus ní féidir iad a léamh ar mhalairt.
|
||||||
|
none=Níl aon rúin ann fós.
|
||||||
|
creation=Cuir Rúnda leis
|
||||||
|
creation.name_placeholder=carachtair alfanumair nó íoslaghda amháin nach féidir a thosú le GITEA_ nó GITHUB_
|
||||||
|
creation.value_placeholder=Ionchur ábhar ar bith. Fágfar spás bán ag tús agus ag deireadh ar lár.
|
||||||
|
creation.success=Tá an rún "%s" curtha leis.
|
||||||
|
creation.failed=Theip ar an rún a chur leis.
|
||||||
|
deletion=Bain rún
|
||||||
|
deletion.description=Is buan rún a bhaint agus ní féidir é a chealú. Lean ort?
|
||||||
|
deletion.success=Tá an rún bainte.
|
||||||
|
deletion.failed=Theip ar rún a bhaint.
|
||||||
|
management=Bainistíocht Rúin
|
||||||
|
|
||||||
[actions]
|
[actions]
|
||||||
|
actions=Gníomhartha
|
||||||
|
|
||||||
|
unit.desc=Bainistigh gníomhartha
|
||||||
|
|
||||||
|
status.unknown=Anaithnid
|
||||||
|
status.waiting=Ag fanacht
|
||||||
|
status.running=Ag rith
|
||||||
|
status.success=Rath
|
||||||
|
status.failure=Teip
|
||||||
|
status.cancelled=Cealaíodh
|
||||||
|
status.skipped=Scipeáilte
|
||||||
|
status.blocked=Blocáilte
|
||||||
|
|
||||||
|
runners=Reathaitheoirí
|
||||||
|
runners.runner_manage_panel=Bainistíocht reathaithe
|
||||||
|
runners.new=Cruthaigh reathaí nua
|
||||||
|
runners.new_notice=Conas reathaí a thosú
|
||||||
|
runners.status=Stádas
|
||||||
|
runners.id=ID
|
||||||
|
runners.name=Ainm
|
||||||
|
runners.owner_type=Cineál
|
||||||
runners.description=Cur síos
|
runners.description=Cur síos
|
||||||
|
runners.labels=Lipéid
|
||||||
|
runners.last_online=Am Ar Líne Deiridh
|
||||||
|
runners.runner_title=Reathaí
|
||||||
|
runners.task_list=Tascanna le déanaí ar an reathaí seo
|
||||||
|
runners.task_list.no_tasks=Níl aon tasc ann fós.
|
||||||
runners.task_list.run=Rith
|
runners.task_list.run=Rith
|
||||||
|
runners.task_list.status=Stádas
|
||||||
|
runners.task_list.repository=Stóras
|
||||||
runners.task_list.commit=Tiomantas
|
runners.task_list.commit=Tiomantas
|
||||||
|
runners.task_list.done_at=Déanta ag
|
||||||
|
runners.edit_runner=Cuir Reathaí in Eagar
|
||||||
|
runners.update_runner=Nuashonrú Athruithe
|
||||||
|
runners.update_runner_success=Nuashonraíodh an Reathaí
|
||||||
|
runners.update_runner_failed=Theip ar an reathaí a nuashonrú
|
||||||
|
runners.delete_runner=Scrios an reathaí seo
|
||||||
|
runners.delete_runner_success=Scriosadh an reathaí go rathúil
|
||||||
|
runners.delete_runner_failed=Theip ar an reathaí a scriosadh
|
||||||
|
runners.delete_runner_header=Deimhnigh an reathaí seo a scriosadh
|
||||||
|
runners.delete_runner_notice=Má tá tasc ar siúl ar an reathaí seo, cuirfear deireadh leis agus marcáil mar theip. Féadfaidh sé sreabhadh oibre tógála a bhriseadh.
|
||||||
|
runners.none=Níl aon reathaí ar fáil
|
||||||
|
runners.status.unspecified=Anaithnid
|
||||||
|
runners.status.idle=Díomhaoin
|
||||||
runners.status.active=Gníomhach
|
runners.status.active=Gníomhach
|
||||||
|
runners.status.offline=As líne
|
||||||
|
runners.version=Leagan
|
||||||
runners.reset_registration_token=Athshocraigh comhartha clár
|
runners.reset_registration_token=Athshocraigh comhartha clár
|
||||||
runners.reset_registration_token_success=D'éirigh le hathshocrú comhartha clárúcháin an dara háit
|
runners.reset_registration_token_success=D'éirigh le hathshocrú comhartha clárúcháin an dara háit
|
||||||
|
|
||||||
@ -2974,11 +3700,54 @@ runs.commit=Tiomantas
|
|||||||
runs.scheduled=Sceidealaithe
|
runs.scheduled=Sceidealaithe
|
||||||
runs.pushed_by=bhrú ag
|
runs.pushed_by=bhrú ag
|
||||||
runs.invalid_workflow_helper=Tá comhad cumraíochta sreabhadh oibre nebhailí. Seiceáil do chomhad cumraithe le do thoil: %s
|
runs.invalid_workflow_helper=Tá comhad cumraíochta sreabhadh oibre nebhailí. Seiceáil do chomhad cumraithe le do thoil: %s
|
||||||
|
runs.no_matching_online_runner_helper=Gan aon reathaí ar líne a mheaitseáil le lipéad: %s
|
||||||
|
runs.no_job_without_needs=Caithfidh post amháin ar a laghad a bheith sa sreabhadh oibre gan spleáchas.
|
||||||
|
runs.no_job=Caithfidh post amháin ar a laghad a bheith sa sreabhadh oibre
|
||||||
|
runs.actor=Aisteoir
|
||||||
|
runs.status=Stádas
|
||||||
|
runs.actors_no_select=Gach aisteoir
|
||||||
|
runs.status_no_select=Gach stádas
|
||||||
|
runs.no_results=Níor mheaitseáil aon torthaí.
|
||||||
|
runs.no_workflows=Níl aon sreafaí oibre ann fós.
|
||||||
|
runs.no_workflows.quick_start=Níl a fhios agam conas tosú le Gitea Actions? Féach <a target="_blank" rel="noopener noreferrer" href="%s">an treoirleabhar mear tosaithe</a>.
|
||||||
|
runs.no_workflows.documentation=Le haghaidh tuilleadh eolais ar Gitea Actions, féach ar <a target="_blank" rel="noopener noreferrer" href="%s">na doiciméid</a>.
|
||||||
|
runs.no_runs=Níl aon rith ag an sreabhadh oibre fós.
|
||||||
|
runs.empty_commit_message=(teachtaireacht tiomantas folamh)
|
||||||
|
runs.expire_log_message=Glanadh logaí toisc go raibh siad ró-sean.
|
||||||
|
|
||||||
|
workflow.disable=Díchumasaigh sreabhadh oibre
|
||||||
|
workflow.disable_success=D'éirigh le sreabhadh oibre '%s' a dhíchumasú.
|
||||||
|
workflow.enable=Cumasaigh sreabhadh oibre
|
||||||
|
workflow.enable_success=Cumasaíodh sreabhadh oibre '%s' go rathúil.
|
||||||
|
workflow.disabled=Tá sreabhadh oibre díchumasaithe
|
||||||
|
workflow.run=Rith Sreabhadh Oibre
|
||||||
|
workflow.not_found=Níor aimsíodh sreabhadh oibre '%s'.
|
||||||
|
workflow.run_success=Ritheann sreabhadh oibre '%s' go rathúil.
|
||||||
|
workflow.from_ref=Úsáid sreabhadh oibre ó
|
||||||
|
workflow.has_workflow_dispatch=Tá comhoibriú ag an gcur i bhfeidhm seo le himeacht workflow_dispatch.
|
||||||
|
|
||||||
|
need_approval_desc=Teastaíonn faomhadh chun sreafaí oibre a rith le haghaidh iarratas tarraingt forc.
|
||||||
|
|
||||||
|
variables=Athróga
|
||||||
|
variables.management=Bainistíocht Athróg
|
||||||
|
variables.creation=Cuir Athróg leis
|
||||||
|
variables.none=Níl aon athróga ann fós.
|
||||||
|
variables.deletion=Bain athróg
|
||||||
|
variables.deletion.description=Tá athróg a bhaint buan agus ní féidir é a chur ar ais. Lean ar aghaidh?
|
||||||
|
variables.description=Cuirfear athróga chuig gníomhartha áirithe agus ní féidir iad a léamh ar mhalairt eile.
|
||||||
|
variables.id_not_exist=Níl athróg le ID %d ann.
|
||||||
|
variables.edit=Cuir Athróg in Eagar
|
||||||
|
variables.deletion.failed=Theip ar athróg a bhaint.
|
||||||
|
variables.deletion.success=Tá an athróg bainte.
|
||||||
|
variables.creation.failed=Theip ar athróg a chur leis.
|
||||||
|
variables.creation.success=Tá an athróg "%s" curtha leis.
|
||||||
|
variables.update.failed=Theip ar athróg a chur in eagar.
|
||||||
|
variables.update.success=Tá an t-athróg curtha in eagar.
|
||||||
|
|
||||||
[projects]
|
[projects]
|
||||||
|
deleted.display_name=Tionscadal scriosta
|
||||||
|
type-1.display_name=Tionscadal Aonair
|
||||||
|
type-2.display_name=Tionscadal Stórais
|
||||||
type-3.display_name=Tionscadal Eagrúcháin
|
type-3.display_name=Tionscadal Eagrúcháin
|
||||||
|
|
||||||
[git.filemode]
|
[git.filemode]
|
||||||
|
@ -10,11 +10,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
packages_model "code.gitea.io/gitea/models/packages"
|
packages_model "code.gitea.io/gitea/models/packages"
|
||||||
container_model "code.gitea.io/gitea/models/packages/container"
|
container_model "code.gitea.io/gitea/models/packages/container"
|
||||||
|
"code.gitea.io/gitea/modules/globallock"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
packages_module "code.gitea.io/gitea/modules/packages"
|
packages_module "code.gitea.io/gitea/modules/packages"
|
||||||
container_module "code.gitea.io/gitea/modules/packages/container"
|
container_module "code.gitea.io/gitea/modules/packages/container"
|
||||||
@ -22,8 +22,6 @@ import (
|
|||||||
packages_service "code.gitea.io/gitea/services/packages"
|
packages_service "code.gitea.io/gitea/services/packages"
|
||||||
)
|
)
|
||||||
|
|
||||||
var uploadVersionMutex sync.Mutex
|
|
||||||
|
|
||||||
// saveAsPackageBlob creates a package blob from an upload
|
// saveAsPackageBlob creates a package blob from an upload
|
||||||
// The uploaded blob gets stored in a special upload version to link them to the package/image
|
// The uploaded blob gets stored in a special upload version to link them to the package/image
|
||||||
func saveAsPackageBlob(ctx context.Context, hsr packages_module.HashedSizeReader, pci *packages_service.PackageCreationInfo) (*packages_model.PackageBlob, error) { //nolint:unparam
|
func saveAsPackageBlob(ctx context.Context, hsr packages_module.HashedSizeReader, pci *packages_service.PackageCreationInfo) (*packages_model.PackageBlob, error) { //nolint:unparam
|
||||||
@ -90,13 +88,20 @@ func mountBlob(ctx context.Context, pi *packages_service.PackageInfo, pb *packag
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func containerPkgName(piOwnerID int64, piName string) string {
|
||||||
|
return fmt.Sprintf("pkg_%d_container_%s", piOwnerID, strings.ToLower(piName))
|
||||||
|
}
|
||||||
|
|
||||||
func getOrCreateUploadVersion(ctx context.Context, pi *packages_service.PackageInfo) (*packages_model.PackageVersion, error) {
|
func getOrCreateUploadVersion(ctx context.Context, pi *packages_service.PackageInfo) (*packages_model.PackageVersion, error) {
|
||||||
var uploadVersion *packages_model.PackageVersion
|
var uploadVersion *packages_model.PackageVersion
|
||||||
|
|
||||||
// FIXME: Replace usage of mutex with database transaction
|
releaser, err := globallock.Lock(ctx, containerPkgName(pi.Owner.ID, pi.Name))
|
||||||
// https://github.com/go-gitea/gitea/pull/21862
|
if err != nil {
|
||||||
uploadVersionMutex.Lock()
|
return nil, err
|
||||||
err := db.WithTx(ctx, func(ctx context.Context) error {
|
}
|
||||||
|
defer releaser()
|
||||||
|
|
||||||
|
err = db.WithTx(ctx, func(ctx context.Context) error {
|
||||||
created := true
|
created := true
|
||||||
p := &packages_model.Package{
|
p := &packages_model.Package{
|
||||||
OwnerID: pi.Owner.ID,
|
OwnerID: pi.Owner.ID,
|
||||||
@ -140,7 +145,6 @@ func getOrCreateUploadVersion(ctx context.Context, pi *packages_service.PackageI
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
uploadVersionMutex.Unlock()
|
|
||||||
|
|
||||||
return uploadVersion, err
|
return uploadVersion, err
|
||||||
}
|
}
|
||||||
@ -173,6 +177,12 @@ func createFileForBlob(ctx context.Context, pv *packages_model.PackageVersion, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
func deleteBlob(ctx context.Context, ownerID int64, image, digest string) error {
|
func deleteBlob(ctx context.Context, ownerID int64, image, digest string) error {
|
||||||
|
releaser, err := globallock.Lock(ctx, containerPkgName(ownerID, image))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer releaser()
|
||||||
|
|
||||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||||
pfds, err := container_model.GetContainerBlobs(ctx, &container_model.BlobSearchOptions{
|
pfds, err := container_model.GetContainerBlobs(ctx, &container_model.BlobSearchOptions{
|
||||||
OwnerID: ownerID,
|
OwnerID: ownerID,
|
||||||
|
@ -45,7 +45,7 @@ func ListHooks(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
hooks := make([]*api.Hook, len(sysHooks))
|
hooks := make([]*api.Hook, len(sysHooks))
|
||||||
for i, hook := range sysHooks {
|
for i, hook := range sysHooks {
|
||||||
h, err := webhook_service.ToHook(setting.AppURL+"/admin", hook)
|
h, err := webhook_service.ToHook(setting.AppURL+"/-/admin", hook)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
|
ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
|
||||||
return
|
return
|
||||||
@ -83,7 +83,7 @@ func GetHook(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h, err := webhook_service.ToHook("/admin/", hook)
|
h, err := webhook_service.ToHook("/-/admin/", hook)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
|
ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
|
||||||
return
|
return
|
||||||
|
@ -100,7 +100,7 @@ func checkCreateHookOption(ctx *context.APIContext, form *api.CreateHookOption)
|
|||||||
func AddSystemHook(ctx *context.APIContext, form *api.CreateHookOption) {
|
func AddSystemHook(ctx *context.APIContext, form *api.CreateHookOption) {
|
||||||
hook, ok := addHook(ctx, form, 0, 0)
|
hook, ok := addHook(ctx, form, 0, 0)
|
||||||
if ok {
|
if ok {
|
||||||
h, err := webhook_service.ToHook(setting.AppSubURL+"/admin", hook)
|
h, err := webhook_service.ToHook(setting.AppSubURL+"/-/admin", hook)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
|
ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
|
||||||
return
|
return
|
||||||
@ -268,7 +268,7 @@ func EditSystemHook(ctx *context.APIContext, form *api.EditHookOption, hookID in
|
|||||||
ctx.Error(http.StatusInternalServerError, "GetSystemOrDefaultWebhook", err)
|
ctx.Error(http.StatusInternalServerError, "GetSystemOrDefaultWebhook", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h, err := webhook_service.ToHook(setting.AppURL+"/admin", updated)
|
h, err := webhook_service.ToHook(setting.AppURL+"/-/admin", updated)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
|
ctx.Error(http.StatusInternalServerError, "convert.ToHook", err)
|
||||||
return
|
return
|
||||||
|
@ -208,7 +208,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cols := make([]string, 0, len(opts.GitPushOptions))
|
cols := make([]string, 0, 2)
|
||||||
|
|
||||||
if isPrivate.Has() {
|
if isPrivate.Has() {
|
||||||
repo.IsPrivate = isPrivate.Value()
|
repo.IsPrivate = isPrivate.Value()
|
||||||
|
@ -185,9 +185,9 @@ func DashboardPost(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if form.From == "monitor" {
|
if form.From == "monitor" {
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/monitor/cron")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/monitor/cron")
|
||||||
} else {
|
} else {
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin")
|
ctx.Redirect(setting.AppSubURL + "/-/admin")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ var (
|
|||||||
func newOAuth2CommonHandlers() *user_setting.OAuth2CommonHandlers {
|
func newOAuth2CommonHandlers() *user_setting.OAuth2CommonHandlers {
|
||||||
return &user_setting.OAuth2CommonHandlers{
|
return &user_setting.OAuth2CommonHandlers{
|
||||||
OwnerID: 0,
|
OwnerID: 0,
|
||||||
BasePathList: fmt.Sprintf("%s/admin/applications", setting.AppSubURL),
|
BasePathList: fmt.Sprintf("%s/-/admin/applications", setting.AppSubURL),
|
||||||
BasePathEditPrefix: fmt.Sprintf("%s/admin/applications/oauth2", setting.AppSubURL),
|
BasePathEditPrefix: fmt.Sprintf("%s/-/admin/applications/oauth2", setting.AppSubURL),
|
||||||
TplAppEdit: tplSettingsOauth2ApplicationEdit,
|
TplAppEdit: tplSettingsOauth2ApplicationEdit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,7 @@ func NewAuthSourcePost(ctx *context.Context) {
|
|||||||
log.Trace("Authentication created by admin(%s): %s", ctx.Doer.Name, form.Name)
|
log.Trace("Authentication created by admin(%s): %s", ctx.Doer.Name, form.Name)
|
||||||
|
|
||||||
ctx.Flash.Success(ctx.Tr("admin.auths.new_success", form.Name))
|
ctx.Flash.Success(ctx.Tr("admin.auths.new_success", form.Name))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/auths")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/auths")
|
||||||
}
|
}
|
||||||
|
|
||||||
// EditAuthSource render editing auth source page
|
// EditAuthSource render editing auth source page
|
||||||
@ -437,7 +437,7 @@ func EditAuthSourcePost(ctx *context.Context) {
|
|||||||
log.Trace("Authentication changed by admin(%s): %d", ctx.Doer.Name, source.ID)
|
log.Trace("Authentication changed by admin(%s): %d", ctx.Doer.Name, source.ID)
|
||||||
|
|
||||||
ctx.Flash.Success(ctx.Tr("admin.auths.update_success"))
|
ctx.Flash.Success(ctx.Tr("admin.auths.update_success"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/auths/" + strconv.FormatInt(form.ID, 10))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/auths/" + strconv.FormatInt(form.ID, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAuthSource response for deleting an auth source
|
// DeleteAuthSource response for deleting an auth source
|
||||||
@ -454,11 +454,11 @@ func DeleteAuthSource(ctx *context.Context) {
|
|||||||
} else {
|
} else {
|
||||||
ctx.Flash.Error(fmt.Sprintf("auth_service.DeleteSource: %v", err))
|
ctx.Flash.Error(fmt.Sprintf("auth_service.DeleteSource: %v", err))
|
||||||
}
|
}
|
||||||
ctx.JSONRedirect(setting.AppSubURL + "/admin/auths/" + url.PathEscape(ctx.PathParam(":authid")))
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/auths/" + url.PathEscape(ctx.PathParam(":authid")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Trace("Authentication deleted by admin(%s): %d", ctx.Doer.Name, source.ID)
|
log.Trace("Authentication deleted by admin(%s): %d", ctx.Doer.Name, source.ID)
|
||||||
|
|
||||||
ctx.Flash.Success(ctx.Tr("admin.auths.deletion_success"))
|
ctx.Flash.Success(ctx.Tr("admin.auths.deletion_success"))
|
||||||
ctx.JSONRedirect(setting.AppSubURL + "/admin/auths")
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/auths")
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ func SendTestMail(ctx *context.Context) {
|
|||||||
ctx.Flash.Info(ctx.Tr("admin.config.test_mail_sent", email))
|
ctx.Flash.Info(ctx.Tr("admin.config.test_mail_sent", email))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/config")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/config")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestCache test the cache settings
|
// TestCache test the cache settings
|
||||||
@ -56,7 +56,7 @@ func TestCache(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/config")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/config")
|
||||||
}
|
}
|
||||||
|
|
||||||
func shadowPasswordKV(cfgItem, splitter string) string {
|
func shadowPasswordKV(cfgItem, splitter string) string {
|
||||||
|
@ -134,7 +134,7 @@ func ActivateEmail(ctx *context.Context) {
|
|||||||
ctx.Flash.Info(ctx.Tr("admin.emails.updated"))
|
ctx.Flash.Info(ctx.Tr("admin.emails.updated"))
|
||||||
}
|
}
|
||||||
|
|
||||||
redirect, _ := url.Parse(setting.AppSubURL + "/admin/emails")
|
redirect, _ := url.Parse(setting.AppSubURL + "/-/admin/emails")
|
||||||
q := url.Values{}
|
q := url.Values{}
|
||||||
if val := ctx.FormTrim("q"); len(val) > 0 {
|
if val := ctx.FormTrim("q"); len(val) > 0 {
|
||||||
q.Set("q", val)
|
q.Set("q", val)
|
||||||
|
@ -36,8 +36,8 @@ func DefaultOrSystemWebhooks(ctx *context.Context) {
|
|||||||
sys["Title"] = ctx.Tr("admin.systemhooks")
|
sys["Title"] = ctx.Tr("admin.systemhooks")
|
||||||
sys["Description"] = ctx.Tr("admin.systemhooks.desc", "https://docs.gitea.com/usage/webhooks")
|
sys["Description"] = ctx.Tr("admin.systemhooks.desc", "https://docs.gitea.com/usage/webhooks")
|
||||||
sys["Webhooks"], err = webhook.GetSystemWebhooks(ctx, optional.None[bool]())
|
sys["Webhooks"], err = webhook.GetSystemWebhooks(ctx, optional.None[bool]())
|
||||||
sys["BaseLink"] = setting.AppSubURL + "/admin/hooks"
|
sys["BaseLink"] = setting.AppSubURL + "/-/admin/hooks"
|
||||||
sys["BaseLinkNew"] = setting.AppSubURL + "/admin/system-hooks"
|
sys["BaseLinkNew"] = setting.AppSubURL + "/-/admin/system-hooks"
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetWebhooksAdmin", err)
|
ctx.ServerError("GetWebhooksAdmin", err)
|
||||||
return
|
return
|
||||||
@ -46,8 +46,8 @@ func DefaultOrSystemWebhooks(ctx *context.Context) {
|
|||||||
def["Title"] = ctx.Tr("admin.defaulthooks")
|
def["Title"] = ctx.Tr("admin.defaulthooks")
|
||||||
def["Description"] = ctx.Tr("admin.defaulthooks.desc", "https://docs.gitea.com/usage/webhooks")
|
def["Description"] = ctx.Tr("admin.defaulthooks.desc", "https://docs.gitea.com/usage/webhooks")
|
||||||
def["Webhooks"], err = webhook.GetDefaultWebhooks(ctx)
|
def["Webhooks"], err = webhook.GetDefaultWebhooks(ctx)
|
||||||
def["BaseLink"] = setting.AppSubURL + "/admin/hooks"
|
def["BaseLink"] = setting.AppSubURL + "/-/admin/hooks"
|
||||||
def["BaseLinkNew"] = setting.AppSubURL + "/admin/default-hooks"
|
def["BaseLinkNew"] = setting.AppSubURL + "/-/admin/default-hooks"
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetWebhooksAdmin", err)
|
ctx.ServerError("GetWebhooksAdmin", err)
|
||||||
return
|
return
|
||||||
@ -67,5 +67,5 @@ func DeleteDefaultOrSystemWebhook(ctx *context.Context) {
|
|||||||
ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
|
ctx.Flash.Success(ctx.Tr("repo.settings.webhook_deletion_success"))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSONRedirect(setting.AppSubURL + "/admin/hooks")
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/hooks")
|
||||||
}
|
}
|
||||||
|
@ -74,5 +74,5 @@ func EmptyNotices(ctx *context.Context) {
|
|||||||
|
|
||||||
log.Trace("System notices deleted by admin (%s): [start: %d]", ctx.Doer.Name, 0)
|
log.Trace("System notices deleted by admin (%s): [start: %d]", ctx.Doer.Name, 0)
|
||||||
ctx.Flash.Success(ctx.Tr("admin.notices.delete_success"))
|
ctx.Flash.Success(ctx.Tr("admin.notices.delete_success"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/notices")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/notices")
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ func DeletePackageVersion(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Flash.Success(ctx.Tr("packages.settings.delete.success"))
|
ctx.Flash.Success(ctx.Tr("packages.settings.delete.success"))
|
||||||
ctx.JSONRedirect(setting.AppSubURL + "/admin/packages?page=" + url.QueryEscape(ctx.FormString("page")) + "&q=" + url.QueryEscape(ctx.FormString("q")) + "&type=" + url.QueryEscape(ctx.FormString("type")))
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages?page=" + url.QueryEscape(ctx.FormString("page")) + "&q=" + url.QueryEscape(ctx.FormString("q")) + "&type=" + url.QueryEscape(ctx.FormString("type")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func CleanupExpiredData(ctx *context.Context) {
|
func CleanupExpiredData(ctx *context.Context) {
|
||||||
@ -109,5 +109,5 @@ func CleanupExpiredData(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Flash.Success(ctx.Tr("admin.packages.cleanup.success"))
|
ctx.Flash.Success(ctx.Tr("admin.packages.cleanup.success"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/packages")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/packages")
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ func QueueSet(ctx *context.Context) {
|
|||||||
maxNumber, err = strconv.Atoi(maxNumberStr)
|
maxNumber, err = strconv.Atoi(maxNumberStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Flash.Error(ctx.Tr("admin.monitor.queue.settings.maxnumberworkers.error"))
|
ctx.Flash.Error(ctx.Tr("admin.monitor.queue.settings.maxnumberworkers.error"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/monitor/queue/" + strconv.FormatInt(qid, 10))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if maxNumber < -1 {
|
if maxNumber < -1 {
|
||||||
@ -65,7 +65,7 @@ func QueueSet(ctx *context.Context) {
|
|||||||
|
|
||||||
mq.SetWorkerMaxNumber(maxNumber)
|
mq.SetWorkerMaxNumber(maxNumber)
|
||||||
ctx.Flash.Success(ctx.Tr("admin.monitor.queue.settings.changed"))
|
ctx.Flash.Success(ctx.Tr("admin.monitor.queue.settings.changed"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/monitor/queue/" + strconv.FormatInt(qid, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
func QueueRemoveAllItems(ctx *context.Context) {
|
func QueueRemoveAllItems(ctx *context.Context) {
|
||||||
@ -85,5 +85,5 @@ func QueueRemoveAllItems(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Flash.Success(ctx.Tr("admin.monitor.queue.settings.remove_all_items_done"))
|
ctx.Flash.Success(ctx.Tr("admin.monitor.queue.settings.remove_all_items_done"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/monitor/queue/" + strconv.FormatInt(qid, 10))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/monitor/queue/" + strconv.FormatInt(qid, 10))
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ func DeleteRepo(ctx *context.Context) {
|
|||||||
log.Trace("Repository deleted: %s", repo.FullName())
|
log.Trace("Repository deleted: %s", repo.FullName())
|
||||||
|
|
||||||
ctx.Flash.Success(ctx.Tr("repo.settings.deletion_success"))
|
ctx.Flash.Success(ctx.Tr("repo.settings.deletion_success"))
|
||||||
ctx.JSONRedirect(setting.AppSubURL + "/admin/repos?page=" + url.QueryEscape(ctx.FormString("page")) + "&sort=" + url.QueryEscape(ctx.FormString("sort")))
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/repos?page=" + url.QueryEscape(ctx.FormString("page")) + "&sort=" + url.QueryEscape(ctx.FormString("sort")))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnadoptedRepos lists the unadopted repositories
|
// UnadoptedRepos lists the unadopted repositories
|
||||||
@ -114,7 +114,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
|
|||||||
|
|
||||||
dirSplit := strings.SplitN(dir, "/", 2)
|
dirSplit := strings.SplitN(dir, "/", 2)
|
||||||
if len(dirSplit) != 2 {
|
if len(dirSplit) != 2 {
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/repos")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/repos")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if user_model.IsErrUserNotExist(err) {
|
if user_model.IsErrUserNotExist(err) {
|
||||||
log.Debug("User does not exist: %s", dirSplit[0])
|
log.Debug("User does not exist: %s", dirSplit[0])
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/repos")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/repos")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.ServerError("GetUserByName", err)
|
ctx.ServerError("GetUserByName", err)
|
||||||
@ -160,5 +160,5 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
ctx.Flash.Success(ctx.Tr("repo.delete_preexisting_success", dir))
|
ctx.Flash.Success(ctx.Tr("repo.delete_preexisting_success", dir))
|
||||||
}
|
}
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/repos/unadopted?search=true&q=" + url.QueryEscape(q) + "&page=" + url.QueryEscape(page))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/repos/unadopted?search=true&q=" + url.QueryEscape(q) + "&page=" + url.QueryEscape(page))
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,5 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func RedirectToDefaultSetting(ctx *context.Context) {
|
func RedirectToDefaultSetting(ctx *context.Context) {
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/actions/runners")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/actions/runners")
|
||||||
}
|
}
|
||||||
|
@ -42,5 +42,5 @@ func Stacktrace(ctx *context.Context) {
|
|||||||
func StacktraceCancel(ctx *context.Context) {
|
func StacktraceCancel(ctx *context.Context) {
|
||||||
pid := ctx.PathParam("pid")
|
pid := ctx.PathParam("pid")
|
||||||
process.GetManager().Cancel(process.IDType(pid))
|
process.GetManager().Cancel(process.IDType(pid))
|
||||||
ctx.JSONRedirect(setting.AppSubURL + "/admin/monitor/stacktrace")
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/monitor/stacktrace")
|
||||||
}
|
}
|
||||||
|
@ -215,14 +215,14 @@ func NewUserPost(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Flash.Success(ctx.Tr("admin.users.new_success", u.Name))
|
ctx.Flash.Success(ctx.Tr("admin.users.new_success", u.Name))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/users/" + strconv.FormatInt(u.ID, 10))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + strconv.FormatInt(u.ID, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareUserInfo(ctx *context.Context) *user_model.User {
|
func prepareUserInfo(ctx *context.Context) *user_model.User {
|
||||||
u, err := user_model.GetUserByID(ctx, ctx.PathParamInt64(":userid"))
|
u, err := user_model.GetUserByID(ctx, ctx.PathParamInt64(":userid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if user_model.IsErrUserNotExist(err) {
|
if user_model.IsErrUserNotExist(err) {
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/users")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/users")
|
||||||
} else {
|
} else {
|
||||||
ctx.ServerError("GetUserByID", err)
|
ctx.ServerError("GetUserByID", err)
|
||||||
}
|
}
|
||||||
@ -481,7 +481,7 @@ func EditUserPost(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.Flash.Success(ctx.Tr("admin.users.update_profile_success"))
|
ctx.Flash.Success(ctx.Tr("admin.users.update_profile_success"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteUser response for deleting a user
|
// DeleteUser response for deleting a user
|
||||||
@ -495,7 +495,7 @@ func DeleteUser(ctx *context.Context) {
|
|||||||
// admin should not delete themself
|
// admin should not delete themself
|
||||||
if u.ID == ctx.Doer.ID {
|
if u.ID == ctx.Doer.ID {
|
||||||
ctx.Flash.Error(ctx.Tr("admin.users.cannot_delete_self"))
|
ctx.Flash.Error(ctx.Tr("admin.users.cannot_delete_self"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,16 +503,16 @@ func DeleteUser(ctx *context.Context) {
|
|||||||
switch {
|
switch {
|
||||||
case models.IsErrUserOwnRepos(err):
|
case models.IsErrUserOwnRepos(err):
|
||||||
ctx.Flash.Error(ctx.Tr("admin.users.still_own_repo"))
|
ctx.Flash.Error(ctx.Tr("admin.users.still_own_repo"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
||||||
case models.IsErrUserHasOrgs(err):
|
case models.IsErrUserHasOrgs(err):
|
||||||
ctx.Flash.Error(ctx.Tr("admin.users.still_has_org"))
|
ctx.Flash.Error(ctx.Tr("admin.users.still_has_org"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
||||||
case models.IsErrUserOwnPackages(err):
|
case models.IsErrUserOwnPackages(err):
|
||||||
ctx.Flash.Error(ctx.Tr("admin.users.still_own_packages"))
|
ctx.Flash.Error(ctx.Tr("admin.users.still_own_packages"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
||||||
case models.IsErrDeleteLastAdminUser(err):
|
case models.IsErrDeleteLastAdminUser(err):
|
||||||
ctx.Flash.Error(ctx.Tr("auth.last_admin"))
|
ctx.Flash.Error(ctx.Tr("auth.last_admin"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + url.PathEscape(ctx.PathParam(":userid")))
|
||||||
default:
|
default:
|
||||||
ctx.ServerError("DeleteUser", err)
|
ctx.ServerError("DeleteUser", err)
|
||||||
}
|
}
|
||||||
@ -521,7 +521,7 @@ func DeleteUser(ctx *context.Context) {
|
|||||||
log.Trace("Account deleted by admin (%s): %s", ctx.Doer.Name, u.Name)
|
log.Trace("Account deleted by admin (%s): %s", ctx.Doer.Name, u.Name)
|
||||||
|
|
||||||
ctx.Flash.Success(ctx.Tr("admin.users.deletion_success"))
|
ctx.Flash.Success(ctx.Tr("admin.users.deletion_success"))
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/users")
|
ctx.Redirect(setting.AppSubURL + "/-/admin/users")
|
||||||
}
|
}
|
||||||
|
|
||||||
// AvatarPost response for change user's avatar request
|
// AvatarPost response for change user's avatar request
|
||||||
@ -538,7 +538,7 @@ func AvatarPost(ctx *context.Context) {
|
|||||||
ctx.Flash.Success(ctx.Tr("settings.update_user_avatar_success"))
|
ctx.Flash.Success(ctx.Tr("settings.update_user_avatar_success"))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/users/" + strconv.FormatInt(u.ID, 10))
|
ctx.Redirect(setting.AppSubURL + "/-/admin/users/" + strconv.FormatInt(u.ID, 10))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAvatar render delete avatar page
|
// DeleteAvatar render delete avatar page
|
||||||
@ -552,5 +552,5 @@ func DeleteAvatar(ctx *context.Context) {
|
|||||||
ctx.Flash.Error(err.Error())
|
ctx.Flash.Error(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSONRedirect(setting.AppSubURL + "/admin/users/" + strconv.FormatInt(u.ID, 10))
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/users/" + strconv.FormatInt(u.ID, 10))
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ func autoSignIn(ctx *context.Context) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Csrf.DeleteCookie(ctx)
|
ctx.Csrf.PrepareForSessionUser(ctx)
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,8 +359,8 @@ func handleSignInFull(ctx *context.Context, u *user_model.User, remember, obeyRe
|
|||||||
ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req)
|
ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear whatever CSRF cookie has right now, force to generate a new one
|
// force to generate a new CSRF token
|
||||||
ctx.Csrf.DeleteCookie(ctx)
|
ctx.Csrf.PrepareForSessionUser(ctx)
|
||||||
|
|
||||||
// Register last login
|
// Register last login
|
||||||
if err := user_service.UpdateUser(ctx, u, &user_service.UpdateOptions{SetLastLogin: true}); err != nil {
|
if err := user_service.UpdateUser(ctx, u, &user_service.UpdateOptions{SetLastLogin: true}); err != nil {
|
||||||
@ -804,6 +804,8 @@ func handleAccountActivation(ctx *context.Context, user *user_model.User) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.Csrf.PrepareForSessionUser(ctx)
|
||||||
|
|
||||||
if err := resetLocale(ctx, user); err != nil {
|
if err := resetLocale(ctx, user); err != nil {
|
||||||
ctx.ServerError("resetLocale", err)
|
ctx.ServerError("resetLocale", err)
|
||||||
return
|
return
|
||||||
|
@ -358,8 +358,8 @@ func handleOAuth2SignIn(ctx *context.Context, source *auth.Source, u *user_model
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear whatever CSRF cookie has right now, force to generate a new one
|
// force to generate a new CSRF token
|
||||||
ctx.Csrf.DeleteCookie(ctx)
|
ctx.Csrf.PrepareForSessionUser(ctx)
|
||||||
|
|
||||||
if err := resetLocale(ctx, u); err != nil {
|
if err := resetLocale(ctx, u); err != nil {
|
||||||
ctx.ServerError("resetLocale", err)
|
ctx.ServerError("resetLocale", err)
|
||||||
|
@ -166,7 +166,7 @@ func setMergeTarget(ctx *context.Context, pull *issues_model.PullRequest) {
|
|||||||
ctx.Data["BaseTarget"] = pull.BaseBranch
|
ctx.Data["BaseTarget"] = pull.BaseBranch
|
||||||
headBranchLink := ""
|
headBranchLink := ""
|
||||||
if pull.Flow == issues_model.PullRequestFlowGithub {
|
if pull.Flow == issues_model.PullRequestFlowGithub {
|
||||||
b, err := git_model.GetBranch(ctx, ctx.Repo.Repository.ID, pull.HeadBranch)
|
b, err := git_model.GetBranch(ctx, pull.HeadRepoID, pull.HeadBranch)
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
if !b.IsDeleted {
|
if !b.IsDeleted {
|
||||||
@ -887,8 +887,6 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pull.HeadRepo != nil {
|
if pull.HeadRepo != nil {
|
||||||
ctx.Data["SourcePath"] = pull.HeadRepo.Link() + "/src/commit/" + endCommitID
|
|
||||||
|
|
||||||
if !pull.HasMerged && ctx.Doer != nil {
|
if !pull.HasMerged && ctx.Doer != nil {
|
||||||
perm, err := access_model.GetUserRepoPermission(ctx, pull.HeadRepo, ctx.Doer)
|
perm, err := access_model.GetUserRepoPermission(ctx, pull.HeadRepo, ctx.Doer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -76,7 +76,7 @@ func getRunnersCtx(ctx *context.Context) (*runnersCtx, error) {
|
|||||||
IsAdmin: true,
|
IsAdmin: true,
|
||||||
RunnersTemplate: tplAdminRunners,
|
RunnersTemplate: tplAdminRunners,
|
||||||
RunnerEditTemplate: tplAdminRunnerEdit,
|
RunnerEditTemplate: tplAdminRunnerEdit,
|
||||||
RedirectLink: setting.AppSubURL + "/admin/actions/runners/",
|
RedirectLink: setting.AppSubURL + "/-/admin/actions/runners/",
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) {
|
|||||||
RepoID: 0,
|
RepoID: 0,
|
||||||
IsGlobal: true,
|
IsGlobal: true,
|
||||||
VariablesTemplate: tplAdminVariables,
|
VariablesTemplate: tplAdminVariables,
|
||||||
RedirectLink: setting.AppSubURL + "/admin/actions/variables",
|
RedirectLink: setting.AppSubURL + "/-/admin/actions/variables",
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,8 +100,8 @@ func getOwnerRepoCtx(ctx *context.Context) (*ownerRepoCtx, error) {
|
|||||||
return &ownerRepoCtx{
|
return &ownerRepoCtx{
|
||||||
IsAdmin: true,
|
IsAdmin: true,
|
||||||
IsSystemWebhook: ctx.PathParam(":configType") == "system-hooks",
|
IsSystemWebhook: ctx.PathParam(":configType") == "system-hooks",
|
||||||
Link: path.Join(setting.AppSubURL, "/admin/hooks"),
|
Link: path.Join(setting.AppSubURL, "/-/admin/hooks"),
|
||||||
LinkNew: path.Join(setting.AppSubURL, "/admin/", ctx.PathParam(":configType")),
|
LinkNew: path.Join(setting.AppSubURL, "/-/admin/", ctx.PathParam(":configType")),
|
||||||
NewTemplate: tplAdminHookNew,
|
NewTemplate: tplAdminHookNew,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -683,7 +683,7 @@ func registerRoutes(m *web.Router) {
|
|||||||
adminReq := verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: true, AdminRequired: true})
|
adminReq := verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: true, AdminRequired: true})
|
||||||
|
|
||||||
// ***** START: Admin *****
|
// ***** START: Admin *****
|
||||||
m.Group("/admin", func() {
|
m.Group("/-/admin", func() {
|
||||||
m.Get("", admin.Dashboard)
|
m.Get("", admin.Dashboard)
|
||||||
m.Get("/system_status", admin.SystemStatus)
|
m.Get("/system_status", admin.SystemStatus)
|
||||||
m.Post("", web.Bind(forms.AdminDashboardForm{}), admin.DashboardPost)
|
m.Post("", web.Bind(forms.AdminDashboardForm{}), admin.DashboardPost)
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
@ -24,10 +23,10 @@ import (
|
|||||||
// ProcReceive handle proc receive work
|
// ProcReceive handle proc receive work
|
||||||
func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, opts *private.HookOptions) ([]private.HookProcReceiveRefResult, error) {
|
func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Repository, opts *private.HookOptions) ([]private.HookProcReceiveRefResult, error) {
|
||||||
results := make([]private.HookProcReceiveRefResult, 0, len(opts.OldCommitIDs))
|
results := make([]private.HookProcReceiveRefResult, 0, len(opts.OldCommitIDs))
|
||||||
|
forcePush := opts.GitPushOptions.Bool(private.GitPushOptionForcePush)
|
||||||
topicBranch := opts.GitPushOptions["topic"]
|
topicBranch := opts.GitPushOptions["topic"]
|
||||||
forcePush, _ := strconv.ParseBool(opts.GitPushOptions["force-push"])
|
|
||||||
title := strings.TrimSpace(opts.GitPushOptions["title"])
|
title := strings.TrimSpace(opts.GitPushOptions["title"])
|
||||||
description := strings.TrimSpace(opts.GitPushOptions["description"]) // TODO: Add more options?
|
description := strings.TrimSpace(opts.GitPushOptions["description"])
|
||||||
objectFormat := git.ObjectFormatFromName(repo.ObjectFormatName)
|
objectFormat := git.ObjectFormatFromName(repo.ObjectFormatName)
|
||||||
userName := strings.ToLower(opts.UserName)
|
userName := strings.ToLower(opts.UserName)
|
||||||
|
|
||||||
@ -56,19 +55,19 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
|
|||||||
}
|
}
|
||||||
|
|
||||||
baseBranchName := opts.RefFullNames[i].ForBranchName()
|
baseBranchName := opts.RefFullNames[i].ForBranchName()
|
||||||
curentTopicBranch := ""
|
currentTopicBranch := ""
|
||||||
if !gitRepo.IsBranchExist(baseBranchName) {
|
if !gitRepo.IsBranchExist(baseBranchName) {
|
||||||
// try match refs/for/<target-branch>/<topic-branch>
|
// try match refs/for/<target-branch>/<topic-branch>
|
||||||
for p, v := range baseBranchName {
|
for p, v := range baseBranchName {
|
||||||
if v == '/' && gitRepo.IsBranchExist(baseBranchName[:p]) && p != len(baseBranchName)-1 {
|
if v == '/' && gitRepo.IsBranchExist(baseBranchName[:p]) && p != len(baseBranchName)-1 {
|
||||||
curentTopicBranch = baseBranchName[p+1:]
|
currentTopicBranch = baseBranchName[p+1:]
|
||||||
baseBranchName = baseBranchName[:p]
|
baseBranchName = baseBranchName[:p]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(topicBranch) == 0 && len(curentTopicBranch) == 0 {
|
if len(topicBranch) == 0 && len(currentTopicBranch) == 0 {
|
||||||
results = append(results, private.HookProcReceiveRefResult{
|
results = append(results, private.HookProcReceiveRefResult{
|
||||||
OriginalRef: opts.RefFullNames[i],
|
OriginalRef: opts.RefFullNames[i],
|
||||||
OldOID: opts.OldCommitIDs[i],
|
OldOID: opts.OldCommitIDs[i],
|
||||||
@ -78,18 +77,18 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(curentTopicBranch) == 0 {
|
if len(currentTopicBranch) == 0 {
|
||||||
curentTopicBranch = topicBranch
|
currentTopicBranch = topicBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
// because different user maybe want to use same topic,
|
// because different user maybe want to use same topic,
|
||||||
// So it's better to make sure the topic branch name
|
// So it's better to make sure the topic branch name
|
||||||
// has user name prefix
|
// has username prefix
|
||||||
var headBranch string
|
var headBranch string
|
||||||
if !strings.HasPrefix(curentTopicBranch, userName+"/") {
|
if !strings.HasPrefix(currentTopicBranch, userName+"/") {
|
||||||
headBranch = userName + "/" + curentTopicBranch
|
headBranch = userName + "/" + currentTopicBranch
|
||||||
} else {
|
} else {
|
||||||
headBranch = curentTopicBranch
|
headBranch = currentTopicBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
pr, err := issues_model.GetUnmergedPullRequest(ctx, repo.ID, repo.ID, headBranch, baseBranchName, issues_model.PullRequestFlowAGit)
|
pr, err := issues_model.GetUnmergedPullRequest(ctx, repo.ID, repo.ID, headBranch, baseBranchName, issues_model.PullRequestFlowAGit)
|
||||||
@ -178,7 +177,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !forcePush {
|
if !forcePush.Value() {
|
||||||
output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").
|
output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").
|
||||||
AddDynamicArguments(oldCommitID, "^"+opts.NewCommitIDs[i]).
|
AddDynamicArguments(oldCommitID, "^"+opts.NewCommitIDs[i]).
|
||||||
RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: os.Environ()})
|
RunStdString(&git.RunOpts{Dir: repo.RepoPath(), Env: os.Environ()})
|
||||||
|
@ -103,8 +103,8 @@ func handleSignIn(resp http.ResponseWriter, req *http.Request, sess SessionStore
|
|||||||
|
|
||||||
middleware.SetLocaleCookie(resp, user.Language, 0)
|
middleware.SetLocaleCookie(resp, user.Language, 0)
|
||||||
|
|
||||||
// Clear whatever CSRF has right now, force to generate a new one
|
// force to generate a new CSRF token
|
||||||
if ctx := gitea_context.GetWebContext(req); ctx != nil {
|
if ctx := gitea_context.GetWebContext(req); ctx != nil {
|
||||||
ctx.Csrf.DeleteCookie(ctx)
|
ctx.Csrf.PrepareForSessionUser(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,10 +129,8 @@ func (c *csrfProtector) PrepareForSessionUser(ctx *Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if needsNew {
|
if needsNew {
|
||||||
// FIXME: actionId.
|
|
||||||
c.token = GenerateCsrfToken(c.opt.Secret, c.id, "POST", time.Now())
|
c.token = GenerateCsrfToken(c.opt.Secret, c.id, "POST", time.Now())
|
||||||
cookie := newCsrfCookie(&c.opt, c.token)
|
ctx.Resp.Header().Add("Set-Cookie", newCsrfCookie(&c.opt, c.token).String())
|
||||||
ctx.Resp.Header().Add("Set-Cookie", cookie.String())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["CsrfToken"] = c.token
|
ctx.Data["CsrfToken"] = c.token
|
||||||
|
@ -58,6 +58,9 @@ func RequireRepoWriterOr(unitTypes ...unit.Type) func(ctx *Context) {
|
|||||||
func RequireRepoReader(unitType unit.Type) func(ctx *Context) {
|
func RequireRepoReader(unitType unit.Type) func(ctx *Context) {
|
||||||
return func(ctx *Context) {
|
return func(ctx *Context) {
|
||||||
if !ctx.Repo.CanRead(unitType) {
|
if !ctx.Repo.CanRead(unitType) {
|
||||||
|
if unitType == unit.TypeCode && canWriteAsMaintainer(ctx) {
|
||||||
|
return
|
||||||
|
}
|
||||||
if log.IsTrace() {
|
if log.IsTrace() {
|
||||||
if ctx.IsSigned {
|
if ctx.IsSigned {
|
||||||
log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+
|
log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+
|
||||||
|
@ -374,7 +374,7 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Repo.Permission.HasAnyUnitAccessOrEveryoneAccess() {
|
if !ctx.Repo.Permission.HasAnyUnitAccessOrEveryoneAccess() && !canWriteAsMaintainer(ctx) {
|
||||||
if ctx.FormString("go-get") == "1" {
|
if ctx.FormString("go-get") == "1" {
|
||||||
EarlyResponseForGoGetMeta(ctx)
|
EarlyResponseForGoGetMeta(ctx)
|
||||||
return
|
return
|
||||||
@ -1058,3 +1058,11 @@ func GitHookService() func(ctx *Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// canWriteAsMaintainer check if the doer can write to a branch as a maintainer
|
||||||
|
func canWriteAsMaintainer(ctx *Context) bool {
|
||||||
|
branchName := getRefNameFromPath(ctx.Repo, ctx.PathParam("*"), func(branchName string) bool {
|
||||||
|
return issues_model.CanMaintainerWriteToBranch(ctx, ctx.Repo.Permission, branchName, ctx.Doer)
|
||||||
|
})
|
||||||
|
return len(branchName) > 0
|
||||||
|
}
|
||||||
|
@ -114,12 +114,10 @@ func TestRenameUser(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Non usable username", func(t *testing.T) {
|
t.Run("Non usable username", func(t *testing.T) {
|
||||||
usernames := []string{"--diff", "aa.png", ".well-known", "search", "aaa.atom"}
|
usernames := []string{"--diff", ".well-known", "gitea-actions", "aaa.atom", "aa.png"}
|
||||||
for _, username := range usernames {
|
for _, username := range usernames {
|
||||||
t.Run(username, func(t *testing.T) {
|
assert.Error(t, user_model.IsUsableUsername(username), "non-usable username: %s", username)
|
||||||
assert.Error(t, user_model.IsUsableUsername(username))
|
assert.Error(t, RenameUser(db.DefaultContext, user, username), "non-usable username: %s", username)
|
||||||
assert.Error(t, RenameUser(db.DefaultContext, user, username))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<h4 class="ui top attached header">
|
<h4 class="ui top attached header">
|
||||||
{{ctx.Locale.Tr "admin.auths.auth_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}})
|
{{ctx.Locale.Tr "admin.auths.auth_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}})
|
||||||
<div class="ui right">
|
<div class="ui right">
|
||||||
<a class="ui primary tiny button" href="{{AppSubUrl}}/admin/auths/new">{{ctx.Locale.Tr "admin.auths.new"}}</a>
|
<a class="ui primary tiny button" href="{{AppSubUrl}}/-/admin/auths/new">{{ctx.Locale.Tr "admin.auths.new"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached table segment">
|
<div class="ui attached table segment">
|
||||||
@ -23,12 +23,12 @@
|
|||||||
{{range .Sources}}
|
{{range .Sources}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{.ID}}</td>
|
<td>{{.ID}}</td>
|
||||||
<td><a href="{{AppSubUrl}}/admin/auths/{{.ID}}">{{.Name}}</a></td>
|
<td><a href="{{AppSubUrl}}/-/admin/auths/{{.ID}}">{{.Name}}</a></td>
|
||||||
<td>{{.TypeName}}</td>
|
<td>{{.TypeName}}</td>
|
||||||
<td>{{svg (Iif .IsActive "octicon-check" "octicon-x")}}</td>
|
<td>{{svg (Iif .IsActive "octicon-check" "octicon-x")}}</td>
|
||||||
<td>{{DateTime "short" .UpdatedUnix}}</td>
|
<td>{{DateTime "short" .UpdatedUnix}}</td>
|
||||||
<td>{{DateTime "short" .CreatedUnix}}</td>
|
<td>{{DateTime "short" .CreatedUnix}}</td>
|
||||||
<td><a href="{{AppSubUrl}}/admin/auths/{{.ID}}">{{svg "octicon-pencil"}}</a></td>
|
<td><a href="{{AppSubUrl}}/-/admin/auths/{{.ID}}">{{svg "octicon-pencil"}}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -231,7 +231,7 @@
|
|||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<dt class="tw-py-1 tw-flex tw-items-center">{{ctx.Locale.Tr "admin.config.send_test_mail"}}</dt>
|
<dt class="tw-py-1 tw-flex tw-items-center">{{ctx.Locale.Tr "admin.config.send_test_mail"}}</dt>
|
||||||
<dd class="tw-py-0">
|
<dd class="tw-py-0">
|
||||||
<form class="ui form ignore-dirty" action="{{AppSubUrl}}/admin/config/test_mail" method="post">
|
<form class="ui form ignore-dirty" action="{{AppSubUrl}}/-/admin/config/test_mail" method="post">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<div class="ui tiny input">
|
<div class="ui tiny input">
|
||||||
<input type="email" name="email" placeholder="{{ctx.Locale.Tr "admin.config.test_email_placeholder"}}" size="29" required>
|
<input type="email" name="email" placeholder="{{ctx.Locale.Tr "admin.config.test_email_placeholder"}}" size="29" required>
|
||||||
@ -263,7 +263,7 @@
|
|||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<dt class="tw-py-1 tw-flex tw-items-center">{{ctx.Locale.Tr "admin.config.cache_test"}}</dt>
|
<dt class="tw-py-1 tw-flex tw-items-center">{{ctx.Locale.Tr "admin.config.cache_test"}}</dt>
|
||||||
<dd class="tw-py-0">
|
<dd class="tw-py-0">
|
||||||
<form class="ui form ignore-dirty" action="{{AppSubUrl}}/admin/config/test_cache" method="post">
|
<form class="ui form ignore-dirty" action="{{AppSubUrl}}/-/admin/config/test_cache" method="post">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<button class="ui tiny primary button">{{ctx.Locale.Tr "test"}}</button>
|
<button class="ui tiny primary button">{{ctx.Locale.Tr "test"}}</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
{{ctx.Locale.Tr "repository"}}
|
{{ctx.Locale.Tr "repository"}}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
<form class="ui form form-fetch-action" method="post" action="{{AppSubUrl}}/admin/config?key={{.SystemConfig.Repository.OpenWithEditorApps.DynKey}}">
|
<form class="ui form form-fetch-action" method="post" action="{{AppSubUrl}}/-/admin/config?key={{.SystemConfig.Repository.OpenWithEditorApps.DynKey}}">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<details>
|
<details>
|
||||||
<summary>{{ctx.Locale.Tr "admin.config.open_with_editor_app_help"}}</summary>
|
<summary>{{ctx.Locale.Tr "admin.config.open_with_editor_app_help"}}</summary>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
{{ctx.Locale.Tr "admin.monitor.cron"}}
|
{{ctx.Locale.Tr "admin.monitor.cron"}}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached table segment">
|
<div class="ui attached table segment">
|
||||||
<form method="post" action="{{AppSubUrl}}/admin">
|
<form method="post" action="{{AppSubUrl}}/-/admin">
|
||||||
<table class="ui very basic striped table unstackable tw-mb-0">
|
<table class="ui very basic striped table unstackable tw-mb-0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
{{ctx.Locale.Tr "admin.dashboard.maintenance_operations"}}
|
{{ctx.Locale.Tr "admin.dashboard.maintenance_operations"}}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached table segment">
|
<div class="ui attached table segment">
|
||||||
<form method="post" action="{{AppSubUrl}}/admin">
|
<form method="post" action="{{AppSubUrl}}/-/admin">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<table class="ui very basic table tw-mt-0 tw-px-4">
|
<table class="ui very basic table tw-mt-0 tw-px-4">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<p class="center">{{ctx.Locale.Tr "admin.emails.change_email_text"}}</p>
|
<p class="center">{{ctx.Locale.Tr "admin.emails.change_email_text"}}</p>
|
||||||
|
|
||||||
<form class="ui form" id="email-action-form" action="{{AppSubUrl}}/admin/emails/activate" method="post">
|
<form class="ui form" id="email-action-form" action="{{AppSubUrl}}/-/admin/emails/activate" method="post">
|
||||||
{{$.CsrfTokenHtml}}
|
{{$.CsrfTokenHtml}}
|
||||||
|
|
||||||
<input type="hidden" id="query-sort" name="sort" value="{{.SortType}}">
|
<input type="hidden" id="query-sort" name="sort" value="{{.SortType}}">
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
<details class="item toggleable-item" {{if or .PageIsAdminDashboard .PageIsAdminSelfCheck}}open{{end}}>
|
<details class="item toggleable-item" {{if or .PageIsAdminDashboard .PageIsAdminSelfCheck}}open{{end}}>
|
||||||
<summary>{{ctx.Locale.Tr "admin.maintenance"}}</summary>
|
<summary>{{ctx.Locale.Tr "admin.maintenance"}}</summary>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<a class="{{if .PageIsAdminDashboard}}active {{end}}item" href="{{AppSubUrl}}/admin">
|
<a class="{{if .PageIsAdminDashboard}}active {{end}}item" href="{{AppSubUrl}}/-/admin">
|
||||||
{{ctx.Locale.Tr "admin.dashboard"}}
|
{{ctx.Locale.Tr "admin.dashboard"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsAdminSelfCheck}}active {{end}}item" href="{{AppSubUrl}}/admin/self_check">
|
<a class="{{if .PageIsAdminSelfCheck}}active {{end}}item" href="{{AppSubUrl}}/-/admin/self_check">
|
||||||
{{ctx.Locale.Tr "admin.self_check"}}
|
{{ctx.Locale.Tr "admin.self_check"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -16,19 +16,19 @@
|
|||||||
<details class="item toggleable-item" {{if or .PageIsAdminUsers .PageIsAdminBadges .PageIsAdminEmails .PageIsAdminOrganizations .PageIsAdminAuthentications}}open{{end}}>
|
<details class="item toggleable-item" {{if or .PageIsAdminUsers .PageIsAdminBadges .PageIsAdminEmails .PageIsAdminOrganizations .PageIsAdminAuthentications}}open{{end}}>
|
||||||
<summary>{{ctx.Locale.Tr "admin.identity_access"}}</summary>
|
<summary>{{ctx.Locale.Tr "admin.identity_access"}}</summary>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<a class="{{if .PageIsAdminAuthentications}}active {{end}}item" href="{{AppSubUrl}}/admin/auths">
|
<a class="{{if .PageIsAdminAuthentications}}active {{end}}item" href="{{AppSubUrl}}/-/admin/auths">
|
||||||
{{ctx.Locale.Tr "admin.authentication"}}
|
{{ctx.Locale.Tr "admin.authentication"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsAdminOrganizations}}active {{end}}item" href="{{AppSubUrl}}/admin/orgs">
|
<a class="{{if .PageIsAdminOrganizations}}active {{end}}item" href="{{AppSubUrl}}/-/admin/orgs">
|
||||||
{{ctx.Locale.Tr "admin.organizations"}}
|
{{ctx.Locale.Tr "admin.organizations"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsAdminUsers}}active {{end}}item" href="{{AppSubUrl}}/admin/users">
|
<a class="{{if .PageIsAdminUsers}}active {{end}}item" href="{{AppSubUrl}}/-/admin/users">
|
||||||
{{ctx.Locale.Tr "admin.users"}}
|
{{ctx.Locale.Tr "admin.users"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsAdminBadges}}active {{end}}item" href="{{AppSubUrl}}/admin/badges">
|
<a class="{{if .PageIsAdminBadges}}active {{end}}item" href="{{AppSubUrl}}/-/admin/badges">
|
||||||
{{ctx.Locale.Tr "admin.badges"}}
|
{{ctx.Locale.Tr "admin.badges"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsAdminEmails}}active {{end}}item" href="{{AppSubUrl}}/admin/emails">
|
<a class="{{if .PageIsAdminEmails}}active {{end}}item" href="{{AppSubUrl}}/-/admin/emails">
|
||||||
{{ctx.Locale.Tr "admin.emails"}}
|
{{ctx.Locale.Tr "admin.emails"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -37,11 +37,11 @@
|
|||||||
<summary>{{ctx.Locale.Tr "admin.assets"}}</summary>
|
<summary>{{ctx.Locale.Tr "admin.assets"}}</summary>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
{{if .EnablePackages}}
|
{{if .EnablePackages}}
|
||||||
<a class="{{if .PageIsAdminPackages}}active {{end}}item" href="{{AppSubUrl}}/admin/packages">
|
<a class="{{if .PageIsAdminPackages}}active {{end}}item" href="{{AppSubUrl}}/-/admin/packages">
|
||||||
{{ctx.Locale.Tr "packages.title"}}
|
{{ctx.Locale.Tr "packages.title"}}
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
<a class="{{if .PageIsAdminRepositories}}active {{end}}item" href="{{AppSubUrl}}/admin/repos">
|
<a class="{{if .PageIsAdminRepositories}}active {{end}}item" href="{{AppSubUrl}}/-/admin/repos">
|
||||||
{{ctx.Locale.Tr "admin.repositories"}}
|
{{ctx.Locale.Tr "admin.repositories"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -51,22 +51,22 @@
|
|||||||
<details class="item toggleable-item" {{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks .PageIsAdminApplications}}open{{end}}>
|
<details class="item toggleable-item" {{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks .PageIsAdminApplications}}open{{end}}>
|
||||||
<summary>{{ctx.Locale.Tr "admin.integrations"}}</summary>
|
<summary>{{ctx.Locale.Tr "admin.integrations"}}</summary>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<a class="{{if .PageIsAdminApplications}}active {{end}}item" href="{{AppSubUrl}}/admin/applications">
|
<a class="{{if .PageIsAdminApplications}}active {{end}}item" href="{{AppSubUrl}}/-/admin/applications">
|
||||||
{{ctx.Locale.Tr "settings.applications"}}
|
{{ctx.Locale.Tr "settings.applications"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active {{end}}item" href="{{AppSubUrl}}/admin/hooks">
|
<a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active {{end}}item" href="{{AppSubUrl}}/-/admin/hooks">
|
||||||
{{ctx.Locale.Tr "admin.hooks"}}
|
{{ctx.Locale.Tr "admin.hooks"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{if not DisableWebhooks}}
|
{{if not DisableWebhooks}}
|
||||||
<a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active {{end}}item" href="{{AppSubUrl}}/admin/hooks">
|
<a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active {{end}}item" href="{{AppSubUrl}}/-/admin/hooks">
|
||||||
{{ctx.Locale.Tr "admin.hooks"}}
|
{{ctx.Locale.Tr "admin.hooks"}}
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .EnableOAuth2}}
|
{{if .EnableOAuth2}}
|
||||||
<a class="{{if .PageIsAdminApplications}}active {{end}}item" href="{{AppSubUrl}}/admin/applications">
|
<a class="{{if .PageIsAdminApplications}}active {{end}}item" href="{{AppSubUrl}}/-/admin/applications">
|
||||||
{{ctx.Locale.Tr "settings.applications"}}
|
{{ctx.Locale.Tr "settings.applications"}}
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
@ -75,10 +75,10 @@
|
|||||||
<details class="item toggleable-item" {{if or .PageIsSharedSettingsRunners .PageIsSharedSettingsVariables}}open{{end}}>
|
<details class="item toggleable-item" {{if or .PageIsSharedSettingsRunners .PageIsSharedSettingsVariables}}open{{end}}>
|
||||||
<summary>{{ctx.Locale.Tr "actions.actions"}}</summary>
|
<summary>{{ctx.Locale.Tr "actions.actions"}}</summary>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<a class="{{if .PageIsSharedSettingsRunners}}active {{end}}item" href="{{AppSubUrl}}/admin/actions/runners">
|
<a class="{{if .PageIsSharedSettingsRunners}}active {{end}}item" href="{{AppSubUrl}}/-/admin/actions/runners">
|
||||||
{{ctx.Locale.Tr "actions.runners"}}
|
{{ctx.Locale.Tr "actions.runners"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsSharedSettingsVariables}}active {{end}}item" href="{{AppSubUrl}}/admin/actions/variables">
|
<a class="{{if .PageIsSharedSettingsVariables}}active {{end}}item" href="{{AppSubUrl}}/-/admin/actions/variables">
|
||||||
{{ctx.Locale.Tr "actions.variables"}}
|
{{ctx.Locale.Tr "actions.variables"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -87,30 +87,30 @@
|
|||||||
<details class="item toggleable-item" {{if or .PageIsAdminConfig}}open{{end}}>
|
<details class="item toggleable-item" {{if or .PageIsAdminConfig}}open{{end}}>
|
||||||
<summary>{{ctx.Locale.Tr "admin.config"}}</summary>
|
<summary>{{ctx.Locale.Tr "admin.config"}}</summary>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<a class="{{if .PageIsAdminConfigSummary}}active {{end}}item" href="{{AppSubUrl}}/admin/config">
|
<a class="{{if .PageIsAdminConfigSummary}}active {{end}}item" href="{{AppSubUrl}}/-/admin/config">
|
||||||
{{ctx.Locale.Tr "admin.config_summary"}}
|
{{ctx.Locale.Tr "admin.config_summary"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsAdminConfigSettings}}active {{end}}item" href="{{AppSubUrl}}/admin/config/settings">
|
<a class="{{if .PageIsAdminConfigSettings}}active {{end}}item" href="{{AppSubUrl}}/-/admin/config/settings">
|
||||||
{{ctx.Locale.Tr "admin.config_settings"}}
|
{{ctx.Locale.Tr "admin.config_settings"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
<a class="{{if .PageIsAdminNotices}}active {{end}}item" href="{{AppSubUrl}}/admin/notices">
|
<a class="{{if .PageIsAdminNotices}}active {{end}}item" href="{{AppSubUrl}}/-/admin/notices">
|
||||||
{{ctx.Locale.Tr "admin.notices"}}
|
{{ctx.Locale.Tr "admin.notices"}}
|
||||||
</a>
|
</a>
|
||||||
<details class="item toggleable-item" {{if or .PageIsAdminMonitorStats .PageIsAdminMonitorCron .PageIsAdminMonitorQueue .PageIsAdminMonitorStacktrace}}open{{end}}>
|
<details class="item toggleable-item" {{if or .PageIsAdminMonitorStats .PageIsAdminMonitorCron .PageIsAdminMonitorQueue .PageIsAdminMonitorStacktrace}}open{{end}}>
|
||||||
<summary>{{ctx.Locale.Tr "admin.monitor"}}</summary>
|
<summary>{{ctx.Locale.Tr "admin.monitor"}}</summary>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<a class="{{if .PageIsAdminMonitorStats}}active {{end}}item" href="{{AppSubUrl}}/admin/monitor/stats">
|
<a class="{{if .PageIsAdminMonitorStats}}active {{end}}item" href="{{AppSubUrl}}/-/admin/monitor/stats">
|
||||||
{{ctx.Locale.Tr "admin.monitor.stats"}}
|
{{ctx.Locale.Tr "admin.monitor.stats"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsAdminMonitorCron}}active {{end}}item" href="{{AppSubUrl}}/admin/monitor/cron">
|
<a class="{{if .PageIsAdminMonitorCron}}active {{end}}item" href="{{AppSubUrl}}/-/admin/monitor/cron">
|
||||||
{{ctx.Locale.Tr "admin.monitor.cron"}}
|
{{ctx.Locale.Tr "admin.monitor.cron"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsAdminMonitorQueue}}active {{end}}item" href="{{AppSubUrl}}/admin/monitor/queue">
|
<a class="{{if .PageIsAdminMonitorQueue}}active {{end}}item" href="{{AppSubUrl}}/-/admin/monitor/queue">
|
||||||
{{ctx.Locale.Tr "admin.monitor.queues"}}
|
{{ctx.Locale.Tr "admin.monitor.queues"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsAdminMonitorStacktrace}}active {{end}}item" href="{{AppSubUrl}}/admin/monitor/stacktrace">
|
<a class="{{if .PageIsAdminMonitorStacktrace}}active {{end}}item" href="{{AppSubUrl}}/-/admin/monitor/stacktrace">
|
||||||
{{ctx.Locale.Tr "admin.monitor.stacktrace"}}
|
{{ctx.Locale.Tr "admin.monitor.stacktrace"}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th></th>
|
||||||
<th colspan="5">
|
<th colspan="5">
|
||||||
<form class="tw-float-right" method="post" action="{{AppSubUrl}}/admin/notices/empty">
|
<form class="tw-float-right" method="post" action="{{AppSubUrl}}/-/admin/notices/empty">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<button type="submit" class="ui red small button">{{ctx.Locale.Tr "admin.notices.delete_all"}}</button>
|
<button type="submit" class="ui red small button">{{ctx.Locale.Tr "admin.notices.delete_all"}}</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
{{ctx.Locale.Tr "admin.packages.total_size" (FileSize .TotalBlobSize)}},
|
{{ctx.Locale.Tr "admin.packages.total_size" (FileSize .TotalBlobSize)}},
|
||||||
{{ctx.Locale.Tr "admin.packages.unreferenced_size" (FileSize .TotalUnreferencedBlobSize)}})
|
{{ctx.Locale.Tr "admin.packages.unreferenced_size" (FileSize .TotalUnreferencedBlobSize)}})
|
||||||
<div class="ui right">
|
<div class="ui right">
|
||||||
<form method="post" action="{{AppSubUrl}}/admin/packages/cleanup">
|
<form method="post" action="{{AppSubUrl}}/-/admin/packages/cleanup">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<button class="ui primary tiny button">{{ctx.Locale.Tr "admin.packages.cleanup"}}</button>
|
<button class="ui primary tiny button">{{ctx.Locale.Tr "admin.packages.cleanup"}}</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<h4 class="ui top attached header">
|
<h4 class="ui top attached header">
|
||||||
{{ctx.Locale.Tr "admin.repos.repo_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}})
|
{{ctx.Locale.Tr "admin.repos.repo_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}})
|
||||||
<div class="ui right">
|
<div class="ui right">
|
||||||
<a class="ui primary tiny button" href="{{AppSubUrl}}/admin/repos/unadopted">{{ctx.Locale.Tr "admin.repos.unadopted"}}</a>
|
<a class="ui primary tiny button" href="{{AppSubUrl}}/-/admin/repos/unadopted">{{ctx.Locale.Tr "admin.repos.unadopted"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<h4 class="ui top attached header">
|
<h4 class="ui top attached header">
|
||||||
{{ctx.Locale.Tr "admin.repos.unadopted"}}
|
{{ctx.Locale.Tr "admin.repos.unadopted"}}
|
||||||
<div class="ui right">
|
<div class="ui right">
|
||||||
<a class="ui primary tiny button" href="{{AppSubUrl}}/admin/repos">{{ctx.Locale.Tr "admin.repos.repo_manage_panel"}}</a>
|
<a class="ui primary tiny button" href="{{AppSubUrl}}/-/admin/repos">{{ctx.Locale.Tr "admin.repos.repo_manage_panel"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
@ -31,7 +31,7 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<p>{{ctx.Locale.Tr "repo.adopt_preexisting_content" $dir}}</p>
|
<p>{{ctx.Locale.Tr "repo.adopt_preexisting_content" $dir}}</p>
|
||||||
</div>
|
</div>
|
||||||
<form class="ui form" method="post" action="{{AppSubUrl}}/admin/repos/unadopted">
|
<form class="ui form" method="post" action="{{AppSubUrl}}/-/admin/repos/unadopted">
|
||||||
{{$.CsrfTokenHtml}}
|
{{$.CsrfTokenHtml}}
|
||||||
<input type="hidden" name="id" value="{{$dir}}">
|
<input type="hidden" name="id" value="{{$dir}}">
|
||||||
<input type="hidden" name="action" value="adopt">
|
<input type="hidden" name="action" value="adopt">
|
||||||
@ -48,7 +48,7 @@
|
|||||||
<div class="content">
|
<div class="content">
|
||||||
<p>{{ctx.Locale.Tr "repo.delete_preexisting_content" $dir}}</p>
|
<p>{{ctx.Locale.Tr "repo.delete_preexisting_content" $dir}}</p>
|
||||||
</div>
|
</div>
|
||||||
<form class="ui form" method="post" action="{{AppSubUrl}}/admin/repos/unadopted">
|
<form class="ui form" method="post" action="{{AppSubUrl}}/-/admin/repos/unadopted">
|
||||||
{{$.CsrfTokenHtml}}
|
{{$.CsrfTokenHtml}}
|
||||||
<input type="hidden" name="id" value="{{$dir}}">
|
<input type="hidden" name="id" value="{{$dir}}">
|
||||||
<input type="hidden" name="action" value="delete">
|
<input type="hidden" name="action" value="delete">
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<a class="{{if eq .ShowGoroutineList "stacktrace"}}active {{end}}item" href="?show=stacktrace">{{ctx.Locale.Tr "admin.monitor.stacktrace"}}</a>
|
<a class="{{if eq .ShowGoroutineList "stacktrace"}}active {{end}}item" href="?show=stacktrace">{{ctx.Locale.Tr "admin.monitor.stacktrace"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form target="_blank" action="{{AppSubUrl}}/admin/monitor/diagnosis" class="ui form">
|
<form target="_blank" action="{{AppSubUrl}}/-/admin/monitor/diagnosis" class="ui form">
|
||||||
<div class="ui inline field">
|
<div class="ui inline field">
|
||||||
<button class="ui primary small button">{{ctx.Locale.Tr "admin.monitor.download_diagnosis_report"}}</button>
|
<button class="ui primary small button">{{ctx.Locale.Tr "admin.monitor.download_diagnosis_report"}}</button>
|
||||||
<input name="seconds" size="3" maxlength="3" value="10"> {{ctx.Locale.Tr "tool.raw_seconds"}}
|
<input name="seconds" size="3" maxlength="3" value="10"> {{ctx.Locale.Tr "tool.raw_seconds"}}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<h4 class="ui top attached header">
|
<h4 class="ui top attached header">
|
||||||
{{ctx.Locale.Tr "admin.users.user_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}})
|
{{ctx.Locale.Tr "admin.users.user_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}})
|
||||||
<div class="ui right">
|
<div class="ui right">
|
||||||
<a class="ui primary tiny button" href="{{AppSubUrl}}/admin/users/new">{{ctx.Locale.Tr "admin.users.new_account"}}</a>
|
<a class="ui primary tiny button" href="{{AppSubUrl}}/-/admin/users/new">{{ctx.Locale.Tr "admin.users.new_account"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
{{if (or .ShowFooterVersion .PageIsAdmin)}}
|
{{if (or .ShowFooterVersion .PageIsAdmin)}}
|
||||||
{{ctx.Locale.Tr "version"}}:
|
{{ctx.Locale.Tr "version"}}:
|
||||||
{{if .IsAdmin}}
|
{{if .IsAdmin}}
|
||||||
<a href="{{AppSubUrl}}/admin/config">{{AppVer}}</a>
|
<a href="{{AppSubUrl}}/-/admin/config">{{AppVer}}</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{AppVer}}
|
{{AppVer}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -158,7 +158,7 @@
|
|||||||
{{if .IsAdmin}}
|
{{if .IsAdmin}}
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
|
|
||||||
<a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/admin">
|
<a class="{{if .PageIsAdmin}}active {{end}}item" href="{{AppSubUrl}}/-/admin">
|
||||||
{{svg "octicon-server"}}
|
{{svg "octicon-server"}}
|
||||||
{{ctx.Locale.Tr "admin_panel"}}
|
{{ctx.Locale.Tr "admin_panel"}}
|
||||||
</a>
|
</a>
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached guide table segment empty-repo-guide">
|
<div class="ui attached guide table segment empty-repo-guide">
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<h3>{{ctx.Locale.Tr "repo.clone_this_repo"}} <small>{{ctx.Locale.Tr "repo.clone_helper" "http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository"}}</small></h3>
|
<h3>{{ctx.Locale.Tr "repo.clone_this_repo"}} <small>{{ctx.Locale.Tr "repo.clone_helper" "http://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository"}}</small></h3>
|
||||||
|
|
||||||
<div class="repo-button-row">
|
<div class="repo-button-row">
|
||||||
{{if and .CanWriteCode (not .Repository.IsArchived)}}
|
{{if and .CanWriteCode (not .Repository.IsArchived)}}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
<div class="content tw-break-anywhere profile-avatar-name">
|
<div class="content tw-break-anywhere profile-avatar-name">
|
||||||
{{if .ContextUser.FullName}}<span class="header text center">{{.ContextUser.FullName}}</span>{{end}}
|
{{if .ContextUser.FullName}}<span class="header text center">{{.ContextUser.FullName}}</span>{{end}}
|
||||||
<span class="username text center">{{.ContextUser.Name}} {{if .IsAdmin}}
|
<span class="username text center">{{.ContextUser.Name}} {{if .IsAdmin}}
|
||||||
<a class="muted" href="{{AppSubUrl}}/admin/users/{{.ContextUser.ID}}" data-tooltip-content="{{ctx.Locale.Tr "admin.users.details"}}">
|
<a class="muted" href="{{AppSubUrl}}/-/admin/users/{{.ContextUser.ID}}" data-tooltip-content="{{ctx.Locale.Tr "admin.users.details"}}">
|
||||||
{{svg "octicon-gear" 18}}
|
{{svg "octicon-gear" 18}}
|
||||||
</a>
|
</a>
|
||||||
{{end}}</span>
|
{{end}}</span>
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
ref: refs/heads/master
|
@ -0,0 +1,4 @@
|
|||||||
|
[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
filemode = true
|
||||||
|
bare = true
|
@ -0,0 +1,8 @@
|
|||||||
|
This repository will be used to test code search. The snippet below shows its directory structure
|
||||||
|
|
||||||
|
.
|
||||||
|
├── avocado.md
|
||||||
|
├── cucumber.md
|
||||||
|
├── ham.md
|
||||||
|
└── potato
|
||||||
|
└── ham.md
|
@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
ORI_DIR=`pwd`
|
||||||
|
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
|
||||||
|
cd "$ORI_DIR"
|
||||||
|
for i in `ls "$SHELL_FOLDER/post-receive.d"`; do
|
||||||
|
sh "$SHELL_FOLDER/post-receive.d/$i"
|
||||||
|
done
|
@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive
|
7
tests/gitea-repositories-meta/org42/search-by-path.git/hooks/pre-receive
Executable file
7
tests/gitea-repositories-meta/org42/search-by-path.git/hooks/pre-receive
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
ORI_DIR=`pwd`
|
||||||
|
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
|
||||||
|
cd "$ORI_DIR"
|
||||||
|
for i in `ls "$SHELL_FOLDER/pre-receive.d"`; do
|
||||||
|
sh "$SHELL_FOLDER/pre-receive.d/$i"
|
||||||
|
done
|
@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" pre-receive
|
@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
ORI_DIR=`pwd`
|
||||||
|
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
|
||||||
|
cd "$ORI_DIR"
|
||||||
|
for i in `ls "$SHELL_FOLDER/proc-receive.d"`; do
|
||||||
|
sh "$SHELL_FOLDER/proc-receive.d/$i"
|
||||||
|
done
|
@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" proc-receive
|
7
tests/gitea-repositories-meta/org42/search-by-path.git/hooks/update
Executable file
7
tests/gitea-repositories-meta/org42/search-by-path.git/hooks/update
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
ORI_DIR=`pwd`
|
||||||
|
SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
|
||||||
|
cd "$ORI_DIR"
|
||||||
|
for i in `ls "$SHELL_FOLDER/update.d"`; do
|
||||||
|
sh "$SHELL_FOLDER/update.d/$i" $1 $2 $3
|
||||||
|
done
|
@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" update $1 $2 $3
|
@ -0,0 +1,6 @@
|
|||||||
|
# git ls-files --others --exclude-from=.git/info/exclude
|
||||||
|
# Lines that start with '#' are comments.
|
||||||
|
# For a project mostly in C, the following would be a good set of
|
||||||
|
# exclude patterns (uncomment them if you want to use them):
|
||||||
|
# *.[oa]
|
||||||
|
# *~
|
@ -0,0 +1,13 @@
|
|||||||
|
90c1019714259b24fb81711d4416ac0f18667dfa refs/heads/DefaultBranch
|
||||||
|
985f0301dba5e7b34be866819cd15ad3d8f508ee refs/heads/branch2
|
||||||
|
65f1bf27bc3bf70f64657658635e66094edbcb4d refs/heads/develop
|
||||||
|
65f1bf27bc3bf70f64657658635e66094edbcb4d refs/heads/feature/1
|
||||||
|
78fb907e3a3309eae4fe8fef030874cebbf1cd5e refs/heads/home-md-img-check
|
||||||
|
3731fe53b763859aaf83e703ee731f6b9447ff1e refs/heads/master
|
||||||
|
62fb502a7172d4453f0322a2cc85bddffa57f07a refs/heads/pr-to-update
|
||||||
|
4649299398e4d39a5c09eb4f534df6f1e1eb87cc refs/heads/sub-home-md-img-check
|
||||||
|
3fa2f829675543ecfc16b2891aebe8bf0608a8f4 refs/notes/commits
|
||||||
|
4a357436d925b5c974181ff12a994538ddc5a269 refs/pull/2/head
|
||||||
|
5f22f7d0d95d614d25a5b68592adb345a4b5c7fd refs/pull/3/head
|
||||||
|
62fb502a7172d4453f0322a2cc85bddffa57f07a refs/pull/5/head
|
||||||
|
65f1bf27bc3bf70f64657658635e66094edbcb4d refs/tags/v1.1
|
Binary file not shown.
@ -0,0 +1,2 @@
|
|||||||
|
P pack-393dc29256bc27cb2ec73898507df710be7a3cf5.pack
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,14 @@
|
|||||||
|
# pack-refs with: peeled fully-peeled sorted
|
||||||
|
90c1019714259b24fb81711d4416ac0f18667dfa refs/heads/DefaultBranch
|
||||||
|
985f0301dba5e7b34be866819cd15ad3d8f508ee refs/heads/branch2
|
||||||
|
65f1bf27bc3bf70f64657658635e66094edbcb4d refs/heads/develop
|
||||||
|
65f1bf27bc3bf70f64657658635e66094edbcb4d refs/heads/feature/1
|
||||||
|
78fb907e3a3309eae4fe8fef030874cebbf1cd5e refs/heads/home-md-img-check
|
||||||
|
3731fe53b763859aaf83e703ee731f6b9447ff1e refs/heads/master
|
||||||
|
62fb502a7172d4453f0322a2cc85bddffa57f07a refs/heads/pr-to-update
|
||||||
|
4649299398e4d39a5c09eb4f534df6f1e1eb87cc refs/heads/sub-home-md-img-check
|
||||||
|
3fa2f829675543ecfc16b2891aebe8bf0608a8f4 refs/notes/commits
|
||||||
|
4a357436d925b5c974181ff12a994538ddc5a269 refs/pull/2/head
|
||||||
|
5f22f7d0d95d614d25a5b68592adb345a4b5c7fd refs/pull/3/head
|
||||||
|
62fb502a7172d4453f0322a2cc85bddffa57f07a refs/pull/5/head
|
||||||
|
65f1bf27bc3bf70f64657658635e66094edbcb4d refs/tags/v1.1
|
@ -17,7 +17,7 @@ func TestAdminConfig(t *testing.T) {
|
|||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
req := NewRequest(t, "GET", "/admin/config")
|
req := NewRequest(t, "GET", "/-/admin/config")
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
assert.True(t, test.IsNormalPageCompleted(resp.Body.String()))
|
assert.True(t, test.IsNormalPageCompleted(resp.Body.String()))
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@ func TestAdminViewUsers(t *testing.T) {
|
|||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
req := NewRequest(t, "GET", "/admin/users")
|
req := NewRequest(t, "GET", "/-/admin/users")
|
||||||
session.MakeRequest(t, req, http.StatusOK)
|
session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
session = loginUser(t, "user2")
|
session = loginUser(t, "user2")
|
||||||
req = NewRequest(t, "GET", "/admin/users")
|
req = NewRequest(t, "GET", "/-/admin/users")
|
||||||
session.MakeRequest(t, req, http.StatusForbidden)
|
session.MakeRequest(t, req, http.StatusForbidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,11 +31,11 @@ func TestAdminViewUser(t *testing.T) {
|
|||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
req := NewRequest(t, "GET", "/admin/users/1")
|
req := NewRequest(t, "GET", "/-/admin/users/1")
|
||||||
session.MakeRequest(t, req, http.StatusOK)
|
session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
session = loginUser(t, "user2")
|
session = loginUser(t, "user2")
|
||||||
req = NewRequest(t, "GET", "/admin/users/1")
|
req = NewRequest(t, "GET", "/-/admin/users/1")
|
||||||
session.MakeRequest(t, req, http.StatusForbidden)
|
session.MakeRequest(t, req, http.StatusForbidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,8 +51,8 @@ func testSuccessfullEdit(t *testing.T, formData user_model.User) {
|
|||||||
|
|
||||||
func makeRequest(t *testing.T, formData user_model.User, headerCode int) {
|
func makeRequest(t *testing.T, formData user_model.User, headerCode int) {
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
csrf := GetCSRF(t, session, "/admin/users/"+strconv.Itoa(int(formData.ID))+"/edit")
|
csrf := GetUserCSRFToken(t, session)
|
||||||
req := NewRequestWithValues(t, "POST", "/admin/users/"+strconv.Itoa(int(formData.ID))+"/edit", map[string]string{
|
req := NewRequestWithValues(t, "POST", "/-/admin/users/"+strconv.Itoa(int(formData.ID))+"/edit", map[string]string{
|
||||||
"_csrf": csrf,
|
"_csrf": csrf,
|
||||||
"user_name": formData.Name,
|
"user_name": formData.Name,
|
||||||
"login_name": formData.LoginName,
|
"login_name": formData.LoginName,
|
||||||
@ -72,8 +72,8 @@ func TestAdminDeleteUser(t *testing.T) {
|
|||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
|
|
||||||
csrf := GetCSRF(t, session, "/admin/users/8/edit")
|
csrf := GetUserCSRFToken(t, session)
|
||||||
req := NewRequestWithValues(t, "POST", "/admin/users/8/delete", map[string]string{
|
req := NewRequestWithValues(t, "POST", "/-/admin/users/8/delete", map[string]string{
|
||||||
"_csrf": csrf,
|
"_csrf": csrf,
|
||||||
})
|
})
|
||||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||||
|
@ -95,7 +95,7 @@ func TestHTTPSigCert(t *testing.T) {
|
|||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
|
|
||||||
csrf := GetCSRF(t, session, "/user/settings/keys")
|
csrf := GetUserCSRFToken(t, session)
|
||||||
req := NewRequestWithValues(t, "POST", "/user/settings/keys", map[string]string{
|
req := NewRequestWithValues(t, "POST", "/user/settings/keys", map[string]string{
|
||||||
"_csrf": csrf,
|
"_csrf": csrf,
|
||||||
"content": "user1",
|
"content": "user1",
|
||||||
|
@ -177,7 +177,7 @@ func TestAPIGetAll(t *testing.T) {
|
|||||||
var apiOrgList []*api.Organization
|
var apiOrgList []*api.Organization
|
||||||
|
|
||||||
DecodeJSON(t, resp, &apiOrgList)
|
DecodeJSON(t, resp, &apiOrgList)
|
||||||
assert.Len(t, apiOrgList, 12)
|
assert.Len(t, apiOrgList, 13)
|
||||||
assert.Equal(t, "Limited Org 36", apiOrgList[1].FullName)
|
assert.Equal(t, "Limited Org 36", apiOrgList[1].FullName)
|
||||||
assert.Equal(t, "limited", apiOrgList[1].Visibility)
|
assert.Equal(t, "limited", apiOrgList[1].Visibility)
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ func TestAPIGetAll(t *testing.T) {
|
|||||||
resp = MakeRequest(t, req, http.StatusOK)
|
resp = MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
DecodeJSON(t, resp, &apiOrgList)
|
DecodeJSON(t, resp, &apiOrgList)
|
||||||
assert.Len(t, apiOrgList, 8)
|
assert.Len(t, apiOrgList, 9)
|
||||||
assert.Equal(t, "org 17", apiOrgList[0].FullName)
|
assert.Equal(t, "org 17", apiOrgList[0].FullName)
|
||||||
assert.Equal(t, "public", apiOrgList[0].Visibility)
|
assert.Equal(t, "public", apiOrgList[0].Visibility)
|
||||||
}
|
}
|
||||||
|
@ -784,7 +784,7 @@ func TestPackageContainer(t *testing.T) {
|
|||||||
newOwnerName := "newUsername"
|
newOwnerName := "newUsername"
|
||||||
|
|
||||||
req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{
|
req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{
|
||||||
"_csrf": GetCSRF(t, session, "/user/settings"),
|
"_csrf": GetUserCSRFToken(t, session),
|
||||||
"name": newOwnerName,
|
"name": newOwnerName,
|
||||||
"email": "user2@example.com",
|
"email": "user2@example.com",
|
||||||
"language": "en-US",
|
"language": "en-US",
|
||||||
@ -794,7 +794,7 @@ func TestPackageContainer(t *testing.T) {
|
|||||||
t.Run(fmt.Sprintf("Catalog[%s]", newOwnerName), checkCatalog(newOwnerName))
|
t.Run(fmt.Sprintf("Catalog[%s]", newOwnerName), checkCatalog(newOwnerName))
|
||||||
|
|
||||||
req = NewRequestWithValues(t, "POST", "/user/settings", map[string]string{
|
req = NewRequestWithValues(t, "POST", "/user/settings", map[string]string{
|
||||||
"_csrf": GetCSRF(t, session, "/user/settings"),
|
"_csrf": GetUserCSRFToken(t, session),
|
||||||
"name": user.Name,
|
"name": user.Name,
|
||||||
"email": "user2@example.com",
|
"email": "user2@example.com",
|
||||||
"language": "en-US",
|
"language": "en-US",
|
||||||
|
@ -94,9 +94,9 @@ func TestAPISearchRepo(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50&private=false", expectedResults: expectedResults{
|
name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50&private=false", expectedResults: expectedResults{
|
||||||
nil: {count: 35},
|
nil: {count: 36},
|
||||||
user: {count: 35},
|
user: {count: 36},
|
||||||
user2: {count: 35},
|
user2: {count: 36},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -57,14 +57,14 @@ func createAttachment(t *testing.T, session *TestSession, csrf, repoURL, filenam
|
|||||||
func TestCreateAnonymousAttachment(t *testing.T) {
|
func TestCreateAnonymousAttachment(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
session := emptyTestSession(t)
|
session := emptyTestSession(t)
|
||||||
createAttachment(t, session, GetCSRF(t, session, "/user/login"), "user2/repo1", "image.png", generateImg(), http.StatusSeeOther)
|
createAttachment(t, session, GetAnonymousCSRFToken(t, session), "user2/repo1", "image.png", generateImg(), http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateIssueAttachment(t *testing.T) {
|
func TestCreateIssueAttachment(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
const repoURL = "user2/repo1"
|
const repoURL = "user2/repo1"
|
||||||
session := loginUser(t, "user2")
|
session := loginUser(t, "user2")
|
||||||
uuid := createAttachment(t, session, GetCSRF(t, session, repoURL), repoURL, "image.png", generateImg(), http.StatusOK)
|
uuid := createAttachment(t, session, GetUserCSRFToken(t, session), repoURL, "image.png", generateImg(), http.StatusOK)
|
||||||
|
|
||||||
req := NewRequest(t, "GET", repoURL+"/issues/new")
|
req := NewRequest(t, "GET", repoURL+"/issues/new")
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
@ -156,8 +156,8 @@ func addAuthSourceLDAP(t *testing.T, sshKeyAttribute, groupFilter string, groupM
|
|||||||
groupTeamMap = groupMapParams[1]
|
groupTeamMap = groupMapParams[1]
|
||||||
}
|
}
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
csrf := GetCSRF(t, session, "/admin/auths/new")
|
csrf := GetUserCSRFToken(t, session)
|
||||||
req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap, groupTeamMapRemoval))
|
req := NewRequestWithValues(t, "POST", "/-/admin/auths/new", buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap, groupTeamMapRemoval))
|
||||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ func TestLDAPAuthChange(t *testing.T) {
|
|||||||
addAuthSourceLDAP(t, "", "")
|
addAuthSourceLDAP(t, "", "")
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
req := NewRequest(t, "GET", "/admin/auths")
|
req := NewRequest(t, "GET", "/-/admin/auths")
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
doc := NewHTMLParser(t, resp.Body)
|
doc := NewHTMLParser(t, resp.Body)
|
||||||
href, exists := doc.Find("table.table td a").Attr("href")
|
href, exists := doc.Find("table.table td a").Attr("href")
|
||||||
@ -252,14 +252,14 @@ func TestLDAPUserSyncWithEmptyUsernameAttribute(t *testing.T) {
|
|||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
csrf := GetCSRF(t, session, "/admin/auths/new")
|
csrf := GetUserCSRFToken(t, session)
|
||||||
payload := buildAuthSourceLDAPPayload(csrf, "", "", "", "")
|
payload := buildAuthSourceLDAPPayload(csrf, "", "", "", "")
|
||||||
payload["attribute_username"] = ""
|
payload["attribute_username"] = ""
|
||||||
req := NewRequestWithValues(t, "POST", "/admin/auths/new", payload)
|
req := NewRequestWithValues(t, "POST", "/-/admin/auths/new", payload)
|
||||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||||
|
|
||||||
for _, u := range gitLDAPUsers {
|
for _, u := range gitLDAPUsers {
|
||||||
req := NewRequest(t, "GET", "/admin/users?q="+u.UserName)
|
req := NewRequest(t, "GET", "/-/admin/users?q="+u.UserName)
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
@ -487,7 +487,7 @@ func TestLDAPPreventInvalidGroupTeamMap(t *testing.T) {
|
|||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
csrf := GetCSRF(t, session, "/admin/auths/new")
|
csrf := GetUserCSRFToken(t, session)
|
||||||
req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, "", "", `{"NOT_A_VALID_JSON"["MISSING_DOUBLE_POINT"]}`, "off"))
|
req := NewRequestWithValues(t, "POST", "/-/admin/auths/new", buildAuthSourceLDAPPayload(csrf, "", "", `{"NOT_A_VALID_JSON"["MISSING_DOUBLE_POINT"]}`, "off"))
|
||||||
session.MakeRequest(t, req, http.StatusOK) // StatusOK = failed, StatusSeeOther = ok
|
session.MakeRequest(t, req, http.StatusOK) // StatusOK = failed, StatusSeeOther = ok
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ func TestChangeDefaultBranch(t *testing.T) {
|
|||||||
session := loginUser(t, owner.Name)
|
session := loginUser(t, owner.Name)
|
||||||
branchesURL := fmt.Sprintf("/%s/%s/settings/branches", owner.Name, repo.Name)
|
branchesURL := fmt.Sprintf("/%s/%s/settings/branches", owner.Name, repo.Name)
|
||||||
|
|
||||||
csrf := GetCSRF(t, session, branchesURL)
|
csrf := GetUserCSRFToken(t, session)
|
||||||
req := NewRequestWithValues(t, "POST", branchesURL, map[string]string{
|
req := NewRequestWithValues(t, "POST", branchesURL, map[string]string{
|
||||||
"_csrf": csrf,
|
"_csrf": csrf,
|
||||||
"action": "default_branch",
|
"action": "default_branch",
|
||||||
@ -30,7 +30,7 @@ func TestChangeDefaultBranch(t *testing.T) {
|
|||||||
})
|
})
|
||||||
session.MakeRequest(t, req, http.StatusSeeOther)
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||||
|
|
||||||
csrf = GetCSRF(t, session, branchesURL)
|
csrf = GetUserCSRFToken(t, session)
|
||||||
req = NewRequestWithValues(t, "POST", branchesURL, map[string]string{
|
req = NewRequestWithValues(t, "POST", branchesURL, map[string]string{
|
||||||
"_csrf": csrf,
|
"_csrf": csrf,
|
||||||
"action": "default_branch",
|
"action": "default_branch",
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user