Browse Source

Merge branch 'develop' into feature/linguistics

pull/2135/head
tso 9 years ago
parent
commit
2ae1600684
  1. 24
      .gopmfile
  2. 2
      .pkgr.yml
  3. 1
      .travis.yml
  4. 8
      CONTRIBUTING.md
  5. 2
      Makefile
  6. 16
      README.md
  7. 2
      README_ZH.md
  8. 3
      cmd/cert_stub.go
  9. 13
      cmd/serve.go
  10. 18
      cmd/web.go
  11. 12
      conf/app.ini
  12. 6
      conf/locale/TRANSLATORS
  13. 178
      conf/locale/locale_bg-BG.ini
  14. 28
      conf/locale/locale_de-DE.ini
  15. 17
      conf/locale/locale_en-US.ini
  16. 30
      conf/locale/locale_es-ES.ini
  17. 18
      conf/locale/locale_fr-FR.ini
  18. 20
      conf/locale/locale_it-IT.ini
  19. 60
      conf/locale/locale_ja-JP.ini
  20. 20
      conf/locale/locale_lv-LV.ini
  21. 20
      conf/locale/locale_nl-NL.ini
  22. 578
      conf/locale/locale_pl-PL.ini
  23. 94
      conf/locale/locale_pt-BR.ini
  24. 56
      conf/locale/locale_ru-RU.ini
  25. 20
      conf/locale/locale_zh-CN.ini
  26. 366
      conf/locale/locale_zh-HK.ini
  27. 2
      docker/README.md
  28. 4
      docker/build.sh
  29. 5
      gogs.go
  30. 50
      models/action.go
  31. 13
      models/error.go
  32. 8
      models/git_diff.go
  33. 71
      models/login.go
  34. 336
      models/migrations/migrations.go
  35. 3
      models/org.go
  36. 55
      models/pull.go
  37. 21
      models/release.go
  38. 42
      models/repo.go
  39. 10
      models/ssh_key.go
  40. 43
      models/update.go
  41. 84
      models/user.go
  42. 3
      models/webhook_slack.go
  43. 2
      models/wiki.go
  44. 1
      modules/auth/admin.go
  45. 1
      modules/auth/org.go
  46. 5
      modules/auth/repo_form.go
  47. 4
      modules/auth/user_form.go
  48. 6
      modules/base/markdown.go
  49. 13
      modules/base/tool.go
  50. 1125
      modules/bindata/bindata.go
  51. 26
      modules/git/blob.go
  52. 162
      modules/git/commit.go
  53. 36
      modules/git/commit_archive.go
  54. 22
      modules/git/error.go
  55. 125
      modules/git/hooks.go
  56. 30
      modules/git/repo.go
  57. 50
      modules/git/repo_branch.go
  58. 341
      modules/git/repo_commit.go
  59. 14
      modules/git/repo_object.go
  60. 104
      modules/git/repo_pull.go
  61. 117
      modules/git/repo_tag.go
  62. 32
      modules/git/repo_tree.go
  63. 87
      modules/git/sha1.go
  64. 51
      modules/git/signature.go
  65. 20
      modules/git/signature_test.go
  66. 70
      modules/git/submodule.go
  67. 67
      modules/git/tag.go
  68. 157
      modules/git/tree.go
  69. 59
      modules/git/tree_blob.go
  70. 113
      modules/git/tree_entry.go
  71. 82
      modules/git/utils.go
  72. 104
      modules/git/version.go
  73. 5
      modules/middleware/context.go
  74. 15
      modules/middleware/repo.go
  75. 10
      modules/setting/setting.go
  76. 5
      modules/ssh/ssh.go
  77. 7
      modules/ssh/ssh_1.3.go
  78. 9
      modules/template/template.go
  79. 37
      packager/debian/postinst
  80. 24
      packager/hooks/postinst
  81. 8
      public/config.codekit
  82. 57
      public/css/gogs.css
  83. 123
      public/css/highlight-8.9.1/github.css
  84. 0
      public/css/highlight-9.0.0/default.css
  85. 99
      public/css/highlight-9.0.0/github.css
  86. 10
      public/js/gogs.js
  87. 3
      public/js/libs/highlight-8.9.1.pack.js
  88. 4
      public/js/libs/highlight-9.0.0.pack.js
  89. 4
      public/less/_base.less
  90. 5
      public/less/_dashboard.less
  91. 10
      public/less/_markdown.less
  92. 1
      public/less/_organization.less
  93. 39
      public/less/_repository.less
  94. 24
      routers/admin/auths.go
  95. 3
      routers/admin/users.go
  96. 2
      routers/api/v1/admin/users.go
  97. 3
      routers/api/v1/api.go
  98. 5
      routers/api/v1/repo/file.go
  99. 78
      routers/api/v1/user/email.go
  100. 8
      routers/api/v1/utils/convert.go
  101. Some files were not shown because too many files have changed in this diff Show More

24
.gopmfile

@ -3,7 +3,7 @@ path = github.com/gogits/gogs
[deps] [deps]
github.com/bradfitz/gomemcache = commit:72a68649ba github.com/bradfitz/gomemcache = commit:72a68649ba
github.com/codegangsta/cli = commit:0302d39 github.com/codegangsta/cli = commit:b5232bb
github.com/go-macaron/binding = commit:2502aaf github.com/go-macaron/binding = commit:2502aaf
github.com/go-macaron/cache = commit:5617353 github.com/go-macaron/cache = commit:5617353
github.com/go-macaron/captcha = commit:8aa5919 github.com/go-macaron/captcha = commit:8aa5919
@ -16,12 +16,12 @@ github.com/go-macaron/toolbox = commit:ab30a81
github.com/go-sql-driver/mysql = commit:d512f20 github.com/go-sql-driver/mysql = commit:d512f20
github.com/go-xorm/core = commit:acb6f00 github.com/go-xorm/core = commit:acb6f00
github.com/go-xorm/xorm = commit:a8fba4d github.com/go-xorm/xorm = commit:a8fba4d
github.com/gogits/chardet = commit:2404f77725 github.com/gogits/git-shell = commit:1ffc4bc
github.com/gogits/git-shell =
github.com/gogits/go-gogs-client = commit:4b541fa github.com/gogits/go-gogs-client = commit:4b541fa
github.com/issue9/identicon = commit:f8c0d2c github.com/issue9/identicon = commit:f8c0d2c
github.com/klauspost/compress = commit:bcd0709 github.com/kardianos/minwinsvc = commit:cad6b2b
github.com/klauspost/cpuid = commit:8d9fe96 github.com/klauspost/compress = commit:42eb574
github.com/klauspost/cpuid = commit:eebb3ea
github.com/klauspost/crc32 = commit:0aff1ea github.com/klauspost/crc32 = commit:0aff1ea
github.com/lib/pq = commit:11fc39a github.com/lib/pq = commit:11fc39a
github.com/mattn/go-sqlite3 = commit:5651a9d github.com/mattn/go-sqlite3 = commit:5651a9d
@ -29,19 +29,19 @@ github.com/mcuadros/go-version = commit:d52711f
github.com/microcosm-cc/bluemonday = commit:4ac6f27 github.com/microcosm-cc/bluemonday = commit:4ac6f27
github.com/msteinert/pam = commit:02ccfbf github.com/msteinert/pam = commit:02ccfbf
github.com/nfnt/resize = commit:dc93e1b98c github.com/nfnt/resize = commit:dc93e1b98c
github.com/russross/blackfriday = commit:300106c github.com/russross/blackfriday = commit:d18b67a
github.com/shurcooL/sanitized_anchor_name = commit:10ef21a github.com/shurcooL/sanitized_anchor_name = commit:10ef21a
github.com/Unknwon/cae = commit:7f5e046 github.com/Unknwon/cae = commit:7f5e046
github.com/Unknwon/com = commit:28b053d github.com/Unknwon/com = commit:28b053d
github.com/Unknwon/i18n = commit:3b48b66 github.com/Unknwon/i18n = commit:3b48b66
github.com/Unknwon/paginater = commit:7748a72 github.com/Unknwon/paginater = commit:7748a72
golang.org/x/net = golang.org/x/net = commit:d75b190
golang.org/x/text = golang.org/x/text = commit:458f474
golang.org/x/crypto = golang.org/x/crypto = commit:7b85b09
gopkg.in/asn1-ber.v1 = commit:4e86f43 gopkg.in/asn1-ber.v1 = commit:4e86f43
gopkg.in/gomail.v2 = commit:df6fc79 gopkg.in/gomail.v2 = commit:fbb71dd
gopkg.in/ini.v1 = commit:65f8c74 gopkg.in/ini.v1 = commit:a4e5487
gopkg.in/ldap.v2 = e9a325d gopkg.in/ldap.v2 = commit:e9a325d
gopkg.in/macaron.v1 = commit:1c6dd87 gopkg.in/macaron.v1 = commit:1c6dd87
gopkg.in/redis.v2 = commit:e617904962 gopkg.in/redis.v2 = commit:e617904962

2
.pkgr.yml

@ -24,4 +24,4 @@ before:
- mv packager/.godir . - mv packager/.godir .
after: after:
- mv bin/main gogs - mv bin/main gogs
after_install: ./packager/debian/postinst after_install: ./packager/hooks/postinst

1
.travis.yml

@ -1,7 +1,6 @@
language: go language: go
go: go:
- 1.3
- 1.4 - 1.4
- 1.5 - 1.5

8
CONTRIBUTING.md

@ -42,13 +42,7 @@ There is no standard form of making a feature request. Just try to describe the
### Pull Request ### Pull Request
Pull requests are always welcome, but note that **ALL PULL REQUESTS MUST APPLY TO THE `develop` BRANCH**. Please read detailed information on [Wiki](https://github.com/gogits/gogs/wiki/Contributing-Code).
We are always thrilled to receive pull requests, and do our best to process them as fast as possible. Not sure if that typo is worth a pull request? Do it! We will appreciate it.
If your pull request is not accepted on the first try, don't be discouraged! If there's a problem with the implementation, hopefully you received feedback on what to improve.
We're trying very hard to keep Gogs lean and focused. We don't want it to do everything for everybody. This means that we might decide against incorporating a new feature. We believe you do like to discuss with us first in [Gitter](https://gitter.im/gogits/gogs).
### Ask For Help ### Ask For Help

2
Makefile

@ -13,6 +13,8 @@ NOW = $(shell date -u '+%Y%m%d%I%M%S')
.PHONY: build pack release bindata clean .PHONY: build pack release bindata clean
.IGNORE: public/css/gogs.css
build: $(GENERATED) build: $(GENERATED)
go install -ldflags '$(LDFLAGS)' -tags '$(TAGS)' go install -ldflags '$(LDFLAGS)' -tags '$(TAGS)'
cp '$(GOPATH)/bin/gogs' . cp '$(GOPATH)/bin/gogs' .

16
README.md

@ -1,11 +1,9 @@
Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?branch=master)](https://travis-ci.org/gogits/gogs) [![Docker Repository on Quay](https://quay.io/repository/gogs/gogs/status "Docker Repository on Quay")](https://quay.io/repository/gogs/gogs) Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?branch=master)](https://travis-ci.org/gogits/gogs) [![Docker Repository on Quay](https://quay.io/repository/gogs/gogs/status "Docker Repository on Quay")](https://quay.io/repository/gogs/gogs) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/gogs/localized.svg)](https://crowdin.com/project/gogs) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gogits/gogs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
===================== =====================
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gogits/gogs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true)
![](public/img/gogs-large-resize.png) ##### Current version: 0.8.7
##### Current version: 0.7.35 Beta
| Web | UI | Preview | | Web | UI | Preview |
|:-------------:|:-------:|:-------:| |:-------------:|:-------:|:-------:|
@ -15,10 +13,10 @@ Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?bra
### NOTICES ### NOTICES
- Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) has been reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site. - :bangbang: You **MUST** read [CONTRIBUTING.md](CONTRIBUTING.md) for bug report and contributing code. :bangbang:
- The demo site [try.gogs.io](https://try.gogs.io) is running under `develop` branch.
- :bangbang:<span style="color: red">You **MUST** read [CONTRIBUTING.md](CONTRIBUTING.md) before you start filing an issue or making a Pull Request, and **MUST** discuss with us on [Gitter](https://gitter.im/gogits/gogs) for UI changes, otherwise it's high possibilities that we are not going to merge it.</span>:bangbang:
- Please [start discussion](http://forum.gogs.io/category/2/general-discussion) or [ask a question](http://forum.gogs.io/category/4/getting-help) on [the forum](http://forum.gogs.io/). GitHub issue tracker only keeps **bugs** and **feature requests**, all other topics will be closed without reason. - Please [start discussion](http://forum.gogs.io/category/2/general-discussion) or [ask a question](http://forum.gogs.io/category/4/getting-help) on [the forum](http://forum.gogs.io/). GitHub issue tracker only keeps **bugs** and **feature requests**, all other topics will be closed without reason.
- Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) was reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site.
- The demo site [try.gogs.io](https://try.gogs.io) is running under `develop` branch.
- If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**. Thanks! - If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**. Thanks!
- If you're interested in using APIs, we have experimental support with [documentation](https://github.com/gogits/go-gogs-client/wiki). - If you're interested in using APIs, we have experimental support with [documentation](https://github.com/gogits/go-gogs-client/wiki).
- If your team/company is using Gogs and would like to put your logo on [our website](http://gogs.io), contact us by any means. - If your team/company is using Gogs and would like to put your logo on [our website](http://gogs.io), contact us by any means.
@ -87,7 +85,7 @@ There are 5 ways to install Gogs:
### Screencasts ### Screencasts
- [Instalando Gogs no Ubuntu](http://blog.linuxpro.com.br/2015/08/14/instalando-gogs-no-ubuntu/) (Português) - [Instalando Gogs no Ubuntu](https://www.youtube.com/watch?v=4UkHAR1F7ZA) (Português)
### Deploy to Cloud ### Deploy to Cloud

2
README_ZH.md

@ -11,7 +11,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
- 有关基本用法和变更日志,请通过 [使用手册](http://gogs.io/docs/intro/) 查看。 - 有关基本用法和变更日志,请通过 [使用手册](http://gogs.io/docs/intro/) 查看。
- 您可以到 [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) 跟随开发团队的脚步。 - 您可以到 [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) 跟随开发团队的脚步。
- 想要先睹为快?通过 [在线体验](https://try.gogs.io/gogs/gogs) 或查看 **安装部署 -> 二进制安装** 小节 - 想要先睹为快?直接去 [在线体验](https://try.gogs.io/gogs/gogs) 。
- 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.html) 页面获取帮助。 - 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.html) 页面获取帮助。
- 希望帮助多国语言界面的翻译吗?请立即访问 [详情页面](http://gogs.io/docs/features/i18n.html)! - 希望帮助多国语言界面的翻译吗?请立即访问 [详情页面](http://gogs.io/docs/features/i18n.html)!

3
cmd/cert_stub.go

@ -16,8 +16,7 @@ import (
var CmdCert = cli.Command{ var CmdCert = cli.Command{
Name: "cert", Name: "cert",
Usage: "Generate self-signed certificate", Usage: "Generate self-signed certificate",
Description: `Generate a self-signed X.509 certificate for a TLS server. Description: `Please use build tags "cert" to rebuild Gogs in order to have this ability`,
Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
Action: runCert, Action: runCert,
} }

13
cmd/serve.go

@ -17,6 +17,7 @@ import (
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
"github.com/gogits/gogs/models" "github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/httplib" "github.com/gogits/gogs/modules/httplib"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
@ -87,7 +88,7 @@ func fail(userMessage, logMessage string, args ...interface{}) {
os.Exit(1) os.Exit(1)
} }
func handleUpdateTask(uuid string, user *models.User, username, reponame string, isWiki bool) { func handleUpdateTask(uuid string, user, repoUser *models.User, reponame string, isWiki bool) {
task, err := models.GetUpdateTaskByUUID(uuid) task, err := models.GetUpdateTaskByUUID(uuid)
if err != nil { if err != nil {
if models.IsErrUpdateTaskNotExist(err) { if models.IsErrUpdateTaskNotExist(err) {
@ -104,13 +105,13 @@ func handleUpdateTask(uuid string, user *models.User, username, reponame string,
} }
if err = models.Update(task.RefName, task.OldCommitID, task.NewCommitID, if err = models.Update(task.RefName, task.OldCommitID, task.NewCommitID,
user.Name, username, reponame, user.Id); err != nil { user.Name, repoUser.Name, reponame, user.Id); err != nil {
log.GitLogger.Error(2, "Update: %v", err) log.GitLogger.Error(2, "Update: %v", err)
} }
// Ask for running deliver hook and test pull request tasks. // Ask for running deliver hook and test pull request tasks.
reqURL := setting.AppUrl + username + "/" + reponame + "/tasks/trigger?branch=" + reqURL := setting.LocalUrl + repoUser.Name + "/" + reponame + "/tasks/trigger?branch=" +
strings.TrimPrefix(task.RefName, "refs/heads/") strings.TrimPrefix(task.RefName, "refs/heads/") + "&secret=" + base.EncodeMD5(repoUser.Salt)
log.GitLogger.Trace("Trigger task: %s", reqURL) log.GitLogger.Trace("Trigger task: %s", reqURL)
resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{ resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{
@ -163,7 +164,7 @@ func runServ(c *cli.Context) {
if models.IsErrUserNotExist(err) { if models.IsErrUserNotExist(err) {
fail("Repository owner does not exist", "Unregistered owner: %s", username) fail("Repository owner does not exist", "Unregistered owner: %s", username)
} }
fail("Internal error", "Failed to get repository owner(%s): %v", username, err) fail("Internal error", "Failed to get repository owner (%s): %v", username, err)
} }
repo, err := models.GetRepositoryByName(repoUser.Id, reponame) repo, err := models.GetRepositoryByName(repoUser.Id, reponame)
@ -266,7 +267,7 @@ func runServ(c *cli.Context) {
} }
if requestedMode == models.ACCESS_MODE_WRITE { if requestedMode == models.ACCESS_MODE_WRITE {
handleUpdateTask(uuid, user, username, reponame, isWiki) handleUpdateTask(uuid, user, repoUser, reponame, isWiki)
} }
// Update user key activity. // Update user key activity.

18
cmd/web.go

@ -29,6 +29,8 @@ import (
"gopkg.in/ini.v1" "gopkg.in/ini.v1"
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
"github.com/gogits/git-module"
"github.com/gogits/gogs/models" "github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/auth" "github.com/gogits/gogs/modules/auth"
"github.com/gogits/gogs/modules/avatar" "github.com/gogits/gogs/modules/avatar"
@ -78,18 +80,19 @@ func checkVersion() {
// Check dependency version. // Check dependency version.
checkers := []VerChecker{ checkers := []VerChecker{
{"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.4.4.1029"}, {"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.4.4.1029"},
{"github.com/Unknwon/macaron", macaron.Version, "0.5.4"},
{"github.com/go-macaron/binding", binding.Version, "0.1.0"}, {"github.com/go-macaron/binding", binding.Version, "0.1.0"},
{"github.com/go-macaron/cache", cache.Version, "0.1.2"}, {"github.com/go-macaron/cache", cache.Version, "0.1.2"},
{"github.com/go-macaron/csrf", csrf.Version, "0.0.3"}, {"github.com/go-macaron/csrf", csrf.Version, "0.0.3"},
{"github.com/go-macaron/i18n", i18n.Version, "0.2.0"}, {"github.com/go-macaron/i18n", i18n.Version, "0.2.0"},
{"github.com/go-macaron/session", session.Version, "0.1.6"}, {"github.com/go-macaron/session", session.Version, "0.1.6"},
{"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"}, {"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"},
{"gopkg.in/ini.v1", ini.Version, "1.8.1"}, {"gopkg.in/ini.v1", ini.Version, "1.8.4"},
{"gopkg.in/macaron.v1", macaron.Version, "0.8.0"},
{"github.com/gogits/git-shell", git.Version, "0.2.1"},
} }
for _, c := range checkers { for _, c := range checkers {
if !version.Compare(c.Version(), c.Expected, ">=") { if !version.Compare(c.Version(), c.Expected, ">=") {
log.Fatal(4, "Package '%s' version is too old(%s -> %s), did you forget to update?", c.ImportPath, c.Version(), c.Expected) log.Fatal(4, "Package '%s' version is too old (%s -> %s), did you forget to update?", c.ImportPath, c.Version(), c.Expected)
} }
} }
} }
@ -255,10 +258,8 @@ func runWeb(ctx *cli.Context) {
m.Group("/users", func() { m.Group("/users", func() {
m.Get("", admin.Users) m.Get("", admin.Users)
m.Get("/new", admin.NewUser) m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(auth.AdminCrateUserForm{}), admin.NewUserPost)
m.Post("/new", bindIgnErr(auth.AdminCrateUserForm{}), admin.NewUserPost) m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
m.Get("/:userid", admin.EditUser)
m.Post("/:userid", bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
m.Post("/:userid/delete", admin.DeleteUser) m.Post("/:userid/delete", admin.DeleteUser)
}) })
@ -273,8 +274,7 @@ func runWeb(ctx *cli.Context) {
m.Group("/auths", func() { m.Group("/auths", func() {
m.Get("", admin.Authentications) m.Get("", admin.Authentications)
m.Get("/new", admin.NewAuthSource) m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
m.Post("/new", bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
m.Combo("/:authid").Get(admin.EditAuthSource). m.Combo("/:authid").Get(admin.EditAuthSource).
Post(bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost) Post(bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost)
m.Post("/:authid/delete", admin.DeleteAuthSource) m.Post("/:authid/delete", admin.DeleteAuthSource)

12
conf/app.ini

@ -15,6 +15,8 @@ SCRIPT_TYPE = bash
ANSI_CHARSET = ANSI_CHARSET =
; Force every new repository to be private ; Force every new repository to be private
FORCE_PRIVATE = false FORCE_PRIVATE = false
; Global maximum creation limit of repository per user, -1 means no limit
MAX_CREATION_LIMIT = -1
; Patch test queue length, make it as large as possible ; Patch test queue length, make it as large as possible
PULL_REQUEST_QUEUE_LENGTH = 10000 PULL_REQUEST_QUEUE_LENGTH = 10000
@ -46,6 +48,10 @@ DOMAIN = localhost
ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/ ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
HTTP_ADDR = HTTP_ADDR =
HTTP_PORT = 3000 HTTP_PORT = 3000
; Local (DMZ) URL for Gogs workers (such as SSH update) accessing web service.
; In most cases you do not need to change the default value.
; Alter it only if your SSH server node is not the same as HTTP node.
LOCAL_ROOT_URL = http://localhost:%(HTTP_PORT)s/
; Disable SSH feature when not available ; Disable SSH feature when not available
DISABLE_SSH = false DISABLE_SSH = false
; Whether use builtin SSH server or not. ; Whether use builtin SSH server or not.
@ -55,7 +61,6 @@ SSH_PORT = 22
OFFLINE_MODE = false OFFLINE_MODE = false
DISABLE_ROUTER_LOG = false DISABLE_ROUTER_LOG = false
; Generate steps: ; Generate steps:
; $ cd path/to/gogs/custom/https
; $ ./gogs cert -ca=true -duration=8760h0m0s -host=myhost.example.com ; $ ./gogs cert -ca=true -duration=8760h0m0s -host=myhost.example.com
; ;
; Or from a .pfx file exported from the Windows certificate store (do ; Or from a .pfx file exported from the Windows certificate store (do
@ -296,7 +301,8 @@ SCHEDULE = @every 1h
; Repository health check ; Repository health check
[cron.repo_health_check] [cron.repo_health_check]
SCHEDULE = @every 24h SCHEDULE = @every 24h
; Arguments for command 'git fsck', e.g.: "--unreachable --tags" TIMEOUT = 60s
; Arguments for command 'git fsck', e.g. "--unreachable --tags"
; see more on http://git-scm.com/docs/git-fsck/1.7.5 ; see more on http://git-scm.com/docs/git-fsck/1.7.5
ARGS = ARGS =
@ -307,7 +313,7 @@ SCHEDULE = @every 24h
[git] [git]
MAX_GIT_DIFF_LINES = 10000 MAX_GIT_DIFF_LINES = 10000
; Arguments for command 'git gc', e.g.: "--aggressive --auto" ; Arguments for command 'git gc', e.g. "--aggressive --auto"
; see more on http://git-scm.com/docs/git-gc/1.7.5 ; see more on http://git-scm.com/docs/git-gc/1.7.5
GC_ARGS = GC_ARGS =

6
conf/locale/TRANSLATORS

@ -2,18 +2,23 @@
# Entries are in alphabetical order. # Entries are in alphabetical order.
Akihiro YAGASAKI <yaggytter AT momiage DOT com> Akihiro YAGASAKI <yaggytter AT momiage DOT com>
Aleksejs Grocevs <aleksejs AT grocevs DOT pro>
Alexander Steinhöfer <kontakt AT lx-s DOT de> Alexander Steinhöfer <kontakt AT lx-s DOT de>
Alexandre Magno <alexandre DOT mbm AT gmail DOT com> Alexandre Magno <alexandre DOT mbm AT gmail DOT com>
Andrey Nering <andrey AT nering DOT com DOT br> Andrey Nering <andrey AT nering DOT com DOT br>
Arthur Aslanyan <arthur DOT e DOT aslanyan AT gmail DOT com> Arthur Aslanyan <arthur DOT e DOT aslanyan AT gmail DOT com>
Barış Arda Yılmaz <ardayilmazgamer AT gmail DOT com> Barış Arda Yılmaz <ardayilmazgamer AT gmail DOT com>
Christoph Kisfeld <christoph DOT kisfeld AT gmail DOT com> Christoph Kisfeld <christoph DOT kisfeld AT gmail DOT com>
Cysioland
Daniel Speichert <daniel AT speichert DOT pl> Daniel Speichert <daniel AT speichert DOT pl>
David Yzaguirre <dvdyzag AT gmail DOT com>
Dmitriy Nogay <me AT catwhocode DOT ga> Dmitriy Nogay <me AT catwhocode DOT ga>
Ezequiel Gonzalez Rial <gonrial AT gmail DOT com>
Gregor Santner <gdev AT live DOT de> Gregor Santner <gdev AT live DOT de>
Hamid Feizabadi <hamidfzm AT gmail DOT com> Hamid Feizabadi <hamidfzm AT gmail DOT com>
Huimin Wang <wanghm2009 AT hotmail DOT co DOT jp> Huimin Wang <wanghm2009 AT hotmail DOT co DOT jp>
ilko ilko
Ilya Makarov
Lafriks <lafriks AT gmail DOT com> Lafriks <lafriks AT gmail DOT com>
Lauri Ojansivu <x AT xet7 DOT org> Lauri Ojansivu <x AT xet7 DOT org>
Luc Stepniewski <luc AT stepniewski DOT fr> Luc Stepniewski <luc AT stepniewski DOT fr>
@ -25,6 +30,7 @@ Natan Albuquerque <natanalbuquerque5 AT gmail DOT com>
Odilon Junior <odilon DOT junior93 AT gmail DOT com> Odilon Junior <odilon DOT junior93 AT gmail DOT com>
Thomas Fanninger <gogs DOT thomas AT fanninger DOT at> Thomas Fanninger <gogs DOT thomas AT fanninger DOT at>
Tilmann Bach <tilmann AT outlook DOT com> Tilmann Bach <tilmann AT outlook DOT com>
Toni Villena Jiménez <tonivj5 AT gmail DOT com>
Vladimir Vissoultchev <wqweto AT gmail DOT com> Vladimir Vissoultchev <wqweto AT gmail DOT com>
YJSoft <yjsoft AT yjsoft DOT pe DOT kr> YJSoft <yjsoft AT yjsoft DOT pe DOT kr>
Łukasz Jan Niemier <lukasz AT niemier DOT pl> Łukasz Jan Niemier <lukasz AT niemier DOT pl>

178
conf/locale/locale_bg-BG.ini

@ -2,10 +2,10 @@ app_desc=Безпроблемен собствен Git сървър
home=Начало home=Начало
dashboard=Табло dashboard=Табло
explore=Преглед explore=Каталог
help=Помощ help=Помощ
sign_in=Вписване sign_in=Вход
sign_out=Излизане sign_out=Изход
sign_up=Регистрирайте се sign_up=Регистрирайте се
register=Регистрация register=Регистрация
website=Уебсайт website=Уебсайт
@ -28,6 +28,7 @@ organization=Организация
mirror=Огледало mirror=Огледало
new_repo=Ново хранилище new_repo=Ново хранилище
new_migrate=Нова миграция new_migrate=Нова миграция
new_mirror=Ново огледало
new_fork=Ново разклонено хранилище new_fork=Ново разклонено хранилище
new_org=Нова организация new_org=Нова организация
manage_org=Управление на организации manage_org=Управление на организации
@ -38,8 +39,8 @@ your_profile=Вашият профил
your_settings=Вашите настройки your_settings=Вашите настройки
news_feed=Поток новини news_feed=Поток новини
pull_requests=Заявки сливане pull_requests=Заявки за сливане
issues=Проблеми issues=Задачи
cancel=Отказ cancel=Отказ
@ -47,7 +48,7 @@ cancel=Отказ
search=Търсене... search=Търсене...
repository=Хранилище repository=Хранилище
user=Потребител user=Потребител
issue=Проблем issue=Задача
code=Код code=Код
[install] [install]
@ -247,10 +248,11 @@ uid=UID
public_profile=Публичен профил public_profile=Публичен профил
profile_desc=Вашият адрес на ел. поща е публичен и ще бъде използван за всички свързани с профила Ви уведомления и всички уеб базирани операции, направени чрез сайта. profile_desc=Вашият адрес на ел. поща е публичен и ще бъде използван за всички свързани с профила Ви уведомления и всички уеб базирани операции, направени чрез сайта.
password_username_disabled=Нелокални потребители не могат да променят името си от тук.
full_name=Пълно име full_name=Пълно име
website=Уебсайт website=Уебсайт
location=Локация location=Локация
update_profile=Обнови профила update_profile=Запази профила
update_profile_success=Вашият профил е запазен успешно. update_profile_success=Вашият профил е запазен успешно.
change_username=Потребителското име е променено change_username=Потребителското име е променено
change_username_prompt=Този промяна ще засегне всички връзки сочещи към профила Ви. change_username_prompt=Този промяна ще засегне всички връзки сочещи към профила Ви.
@ -260,7 +262,7 @@ cancel=Отказ
enable_custom_avatar=Разреши потребителски аватар enable_custom_avatar=Разреши потребителски аватар
enable_custom_avatar_helper=Без зареждане от Gravatar enable_custom_avatar_helper=Без зареждане от Gravatar
choose_new_avatar=Избор на нов аватар choose_new_avatar=Избор на нов аватар
update_avatar=Обнови настройките на аватара update_avatar=Запази настройките на аватара
uploaded_avatar_not_a_image=Каченият файл не е изображение. uploaded_avatar_not_a_image=Каченият файл не е изображение.
no_custom_avatar_available=Невъзможно използване на външен аватар, защото не е активирано. no_custom_avatar_available=Невъзможно използване на външен аватар, защото не е активирано.
update_avatar_success=Настройките на аватара са запазени успешно. update_avatar_success=Настройките на аватара са запазени успешно.
@ -271,6 +273,7 @@ new_password=Нова парола
retype_new_password=Повторно новата парола retype_new_password=Повторно новата парола
password_incorrect=Въведената парола не е вярна. password_incorrect=Въведената парола не е вярна.
change_password_success=Вашата парола е променена успешно. Вече може да влизате, използвайки тази нова парола. change_password_success=Вашата парола е променена успешно. Вече може да влизате, използвайки тази нова парола.
password_change_disabled=Нелокални потребители не могат да променят паролата си от тук.
emails=Адреси на ел. поща emails=Адреси на ел. поща
manage_emails=Управление на адреси на ел. поща manage_emails=Управление на адреси на ел. поща
@ -302,26 +305,26 @@ ssh_key_deletion_desc=При изтриване на този SSH ключ ще
ssh_key_deletion_success=SSH ключа беше изтрит успешно! ssh_key_deletion_success=SSH ключа беше изтрит успешно!
add_on=Добавен на add_on=Добавен на
last_used=Последно използван на last_used=Последно използван на
no_activity=Няма скорошна активност no_activity=Няма скорошна дейност
key_state_desc=Този ключ е използван през последните 7 дни key_state_desc=Този ключ е използван през последните 7 дни
token_state_desc=Този токен е използван през последните 7 дни token_state_desc=Този API ключ е използван през последните 7 дни
manage_social=Управление на свързани профили в социалните мрежи manage_social=Управление на свързани профили в социалните мрежи
social_desc=Това е списък на свързани профили в социалните мрежи. Премахнете всички, които не разпознавате. social_desc=Това е списък на свързани профили в социалните мрежи. Премахнете всички, които не разпознавате.
unbind=Освобождаване unbind=Освобождаване
unbind_success=Социалния профил е освободен. unbind_success=Социалния профил е освободен.
manage_access_token=Управление на индивидуални токени за достъп manage_access_token=Управление на индивидуални API ключове за достъп
generate_new_token=Генериране на нов токен generate_new_token=Генериране на нов API ключ
tokens_desc=Генерирани токени, които могат да се използват за достъп до API-то на Gogs. tokens_desc=Генерирани API ключове, които могат да се използват за достъп до API на Gogs.
new_token_desc=Всеки токен ще има пълен достъп до Вашия профил. new_token_desc=Всеки API ключ ще има пълен достъп до Вашия профил.
token_name=Име на токена token_name=Име на API ключ
generate_token=Генериране на токен generate_token=Генериране на API ключ
generate_token_succees=Успешно е генериран токен за достъп. Уверете се, че сте го копирали, тъй като няма да можете да го видите отново! generate_token_succees=Успешно е генериран API ключ за достъп. Уверете се, че сте го копирали, тъй като няма да можете да го видите отново!
delete_token=Изтрий delete_token=Изтрий
access_token_deletion=Изтрий индивидуален токен за достъп access_token_deletion=Изтрий индивидуален API ключ за достъп
access_token_deletion_desc=При изтриване на този индивидуален токен за достъп ще се премахнат всички свързани права на приложението. Желаете ли да продължите? access_token_deletion_desc=При изтриване на този индивидуален API ключ за достъп ще се премахнат всички свързани права на приложението. Желаете ли да продължите?
delete_token_success=Индивидуалния токен за достъп е изтрит успешно! Не забравяйте да преконфигурирате приложението също. delete_token_success=Индивидуалният API ключ за достъп е изтрит успешно! Не забравяйте да преконфигурирате приложението също.
delete_account=Изтриване на собствения профил delete_account=Изтриване на собствения профил
delete_prompt=Тази операция ще изтрие Вашия профил завинаги и тя <strong>НЕ МОЖЕ</strong> да бъде отменена в последствие! delete_prompt=Тази операция ще изтрие Вашия профил завинаги и тя <strong>НЕ МОЖЕ</strong> да бъде отменена в последствие!
@ -352,10 +355,13 @@ auto_init=Инициализиране на това хранилище с из
create_repo=Създай хранилище create_repo=Създай хранилище
default_branch=Клон по подразбиране default_branch=Клон по подразбиране
mirror_interval=Интервал на отразяване (часове) mirror_interval=Интервал на отразяване (часове)
mirror_address=Адрес на огледало
mirror_address_desc=Моля включете потребител и парола в адреса ако са нужни.
watchers=Наблюдаващи watchers=Наблюдаващи
stargazers=Харесващи stargazers=Харесващи
forks=Разклонения forks=Разклонения
form.reach_limit_of_creation=Притежателят е достигнал настроения лимит от %d брой хранилища.
form.name_reserved=Името на хранилището '%s' е запазено. form.name_reserved=Името на хранилището '%s' е запазено.
form.name_pattern_not_allowed=Име на хранилището от вида '%s' не е позволено. form.name_pattern_not_allowed=Име на хранилището от вида '%s' не е позволено.
@ -369,6 +375,7 @@ migrate.permission_denied=Недостатъчни права за импорт
migrate.invalid_local_path=Невалиден път - не съществува или не е директория. migrate.invalid_local_path=Невалиден път - не съществува или не е директория.
migrate.failed=Грешка при миграция: %v migrate.failed=Грешка при миграция: %v
mirror_from=огледало от
forked_from=разклонено от forked_from=разклонено от
fork_from_self=Не можете да разклоните хранилище което си е Ваше! fork_from_self=Не можете да разклоните хранилище което си е Ваше!
copy_link=Копирай copy_link=Копирай
@ -388,18 +395,18 @@ create_new_repo_command=Създай ново хранилище чрез ком
push_exist_repo=Предай съществуващо хранилище през командния ред push_exist_repo=Предай съществуващо хранилище през командния ред
repo_is_empty=Това хранилище е празно. Моля проверете по-късно пак! repo_is_empty=Това хранилище е празно. Моля проверете по-късно пак!
code=Code code=Код
branch=Клон branch=Клон
tree=ИН на ревизия tree=ИН на ревизия
filter_branch_and_tag=Филтър по маркер или клон filter_branch_and_tag=Филтър по маркер или клон
branches=Клонове branches=Клонове
tags=Маркери tags=Маркери
issues=Проблеми issues=Задачи
pulls=Заявки сливане pulls=Заявки за сливане
labels=Етикети labels=Етикети
milestones=Етапи milestones=Етапи
commits=Ревизии commits=Ревизии
releases=Издания releases=Версии
file_raw=Директен файл file_raw=Директен файл
file_history=История file_history=История
file_view_raw=Виж директен файл file_view_raw=Виж директен файл
@ -414,7 +421,7 @@ commits.date=Дата
commits.older=По-стари commits.older=По-стари
commits.newer=По-нови commits.newer=По-нови
issues.new=Нов проблем issues.new=Нова задача
issues.new.labels=Етикети issues.new.labels=Етикети
issues.new.no_label=Няма етикет issues.new.no_label=Няма етикет
issues.new.clear_labels=Изчисти етикети issues.new.clear_labels=Изчисти етикети
@ -426,7 +433,7 @@ issues.new.closed_milestone=Затворени етапи
issues.new.assignee=Изпълнител issues.new.assignee=Изпълнител
issues.new.clear_assignee=Изчисти изпълнител issues.new.clear_assignee=Изчисти изпълнител
issues.new.no_assignee=Няма изпълнител issues.new.no_assignee=Няма изпълнител
issues.create=Докладвай проблем issues.create=Създай задача
issues.new_label=Нов етикет issues.new_label=Нов етикет
issues.new_label_placeholder=Име на етикета... issues.new_label_placeholder=Име на етикета...
issues.create_label=Създай етикет issues.create_label=Създай етикет
@ -439,7 +446,7 @@ issues.filter_milestone_no_select=Липсва избран етап
issues.filter_assignee=Изпълнител issues.filter_assignee=Изпълнител
issues.filter_assginee_no_select=Няма избран изпълнител issues.filter_assginee_no_select=Няма избран изпълнител
issues.filter_type=Тип issues.filter_type=Тип
issues.filter_type.all_issues=Всички проблеми issues.filter_type.all_issues=Всички задачи
issues.filter_type.assigned_to_you=Възложени на Вас issues.filter_type.assigned_to_you=Възложени на Вас
issues.filter_type.created_by_you=Създадени от Вас issues.filter_type.created_by_you=Създадени от Вас
issues.filter_type.mentioning_you=Споменават лично issues.filter_type.mentioning_you=Споменават лично
@ -466,7 +473,7 @@ issues.reopen_comment_issue=Kоментирай и oтвори отново
issues.create_comment=Коментирай issues.create_comment=Коментирай
issues.closed_at=`затвори <a id="%[1]s" href="#%[1]s">%[2]s</a>` issues.closed_at=`затвори <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`повторно отвори <a id="%[1]s" href="#%[1]s">%[2]s</a>` issues.reopened_at=`повторно отвори <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`посочи този проблем от ревизия <a id="%[1]s" href="#%[1]s">%[2]s</a>` issues.commit_ref_at=`посочи тази задача от ревизия <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.poster=Участник issues.poster=Участник
issues.admin=Администратор issues.admin=Администратор
issues.owner=Притежател issues.owner=Притежател
@ -478,12 +485,12 @@ issues.save=Запис
issues.label_title=Име на етикета issues.label_title=Име на етикета
issues.label_color=Цвят на етикет issues.label_color=Цвят на етикет
issues.label_count=%d етикети issues.label_count=%d етикети
issues.label_open_issues=%d отворени проблема issues.label_open_issues=%d отворени задачи
issues.label_edit=Редакция issues.label_edit=Редакция
issues.label_delete=Изтрий issues.label_delete=Изтрий
issues.label_modify=Промяна на етикет issues.label_modify=Промяна на етикет
issues.label_deletion=Изтрий етикет issues.label_deletion=Изтрий етикет
issues.label_deletion_desc=При изтриване на този етикет ще се премахне информацията за него във всички свързани проблеми. Желаете ли да продължите? issues.label_deletion_desc=При изтриване на този етикет ще се премахне информацията за него във всички свързани задачи. Желаете ли да продължите?
issues.label_deletion_success=Етикетът е изтрит успешно! issues.label_deletion_success=Етикетът е изтрит успешно!
pulls.new=Нова заявка за сливане pulls.new=Нова заявка за сливане
@ -506,9 +513,9 @@ pulls.merged=Обединени
pulls.has_merged=Тази заявка за сливане е обединена успешно! pulls.has_merged=Тази заявка за сливане е обединена успешно!
pulls.data_broken=Данните от тази заявка за сливане са невалидни поради изтрита информация за някое разклонение. pulls.data_broken=Данните от тази заявка за сливане са невалидни поради изтрита информация за някое разклонение.
pulls.is_checking=Проверката за конфликт все още е в ход. Моля обновете страницата след малко. pulls.is_checking=Проверката за конфликт все още е в ход. Моля обновете страницата след малко.
pulls.can_auto_merge_desc=Можете да извършвате авто-обединяване на тази заявка за сливане. pulls.can_auto_merge_desc=Може да се извърши обединяване на тази заявка за сливане.
pulls.cannot_auto_merge_desc=Не можете да извършите авто-обединяване, защото съществуват конфликти между ревизиите. pulls.cannot_auto_merge_desc=Не може да се извърши обединяване, защото съществуват конфликти между ревизиите.
pulls.cannot_auto_merge_helper=Моля, използвайте инструменти на командния ред за да отстраните проблема. pulls.cannot_auto_merge_helper=Моля, използвайте инструменти на командния ред за да разрешите конфликтите.
pulls.merge_pull_request=Обедини заявка за сливане pulls.merge_pull_request=Обедини заявка за сливане
pulls.open_unmerged_pull_exists=`Невъзможно повторно отваряне, защото вече съществува заявка за сливане (#%d) от същото хранилище със същата информация за обединяване, която чака да бъде извършена` pulls.open_unmerged_pull_exists=`Невъзможно повторно отваряне, защото вече съществува заявка за сливане (#%d) от същото хранилище със същата информация за обединяване, която чака да бъде извършена`
@ -519,7 +526,7 @@ milestones.closed=Затворен %s
milestones.no_due_date=Няма краен срок milestones.no_due_date=Няма краен срок
milestones.open=Отвори milestones.open=Отвори
milestones.close=Затвори milestones.close=Затвори
milestones.new_subheader=Създайте етапи за да организирате проблемите. milestones.new_subheader=Създайте етапи за да организирате задачите.
milestones.create=Създай етап milestones.create=Създай етап
milestones.title=Заглавие milestones.title=Заглавие
milestones.desc=Описание milestones.desc=Описание
@ -533,7 +540,7 @@ milestones.cancel=Отказ
milestones.modify=Промяна на етап milestones.modify=Промяна на етап
milestones.edit_success=Промените в етап '%s' са запазени успешно! milestones.edit_success=Промените в етап '%s' са запазени успешно!
milestones.deletion=Изтрий етап milestones.deletion=Изтрий етап
milestones.deletion_desc=При изтриване на етап ще се премахне информацията за него от всички свързани проблеми. Желаете ли да продължите? milestones.deletion_desc=При изтриване на етап ще се премахне информацията за него от всички свързани задачи. Желаете ли да продължите?
milestones.deletion_success=Етапът е изтрит успешно! milestones.deletion_success=Етапът е изтрит успешно!
wiki=Уики wiki=Уики
@ -559,15 +566,18 @@ settings.hooks=Уеб-куки
settings.githooks=Git куки settings.githooks=Git куки
settings.basic_settings=Основни настройки settings.basic_settings=Основни настройки
settings.site=Официален сайт settings.site=Официален сайт
settings.update_settings=Обнови настройките settings.update_settings=Запази настройките
settings.change_reponame_prompt=Тази промяна ще засегне връзките, които се отнасят до това хранилището. settings.change_reponame_prompt=Тази промяна ще засегне връзките, които се отнасят до това хранилището.
settings.advanced_settings=Advanced Settings settings.advanced_settings=Разширени настройки
settings.wiki_desc=Enable wiki to allow people write documents settings.wiki_desc=Включва уики за да може потребителите да създават документи
settings.issues_desc=Enable builtin lightweight issue tracker settings.use_external_wiki=Използвай външно уики
settings.use_external_issue_tracker=Use external issue tracker settings.external_wiki_url=URL адрес на външно уики
settings.tracker_url_format=External Issue Tracker URL Format settings.external_wiki_url_desc=Посетителите ще бъдат пренасочени към този URL адрес от връзката за раздел уики.
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index. settings.issues_desc=Включва вградена система за проследяване на задачи
settings.pulls_desc=Enable pull requests to accept public contributions settings.use_external_issue_tracker=Използвай външна система за проследяване на задачи
settings.tracker_url_format=Формат на URL адрес на външна система за проследяване на задачи
settings.tracker_url_format_desc=Можете да използвате текстови маркери <code>{user} {repo} {index}</code> за потребителско име, име на хранилище и индекс на задача съответно.
settings.pulls_desc=Включва заявки за сливане за да може да се приемат външни доработки
settings.danger_zone=Опасна зона settings.danger_zone=Опасна зона
settings.transfer=Прехвърли притежание settings.transfer=Прехвърли притежание
settings.transfer_desc=Прехвърля това хранилище на друг потребител или към организация, в която имате права на администратор. settings.transfer_desc=Прехвърля това хранилище на друг потребител или към организация, в която имате права на администратор.
@ -578,11 +588,11 @@ settings.transfer_notices_1=- Вие ще загубите достъп, ако
settings.transfer_notices_2=- Вие ще запазите достъпа си, ако новият притежател е организация и ако вие сте един от притежателите ѝ. settings.transfer_notices_2=- Вие ще запазите достъпа си, ако новият притежател е организация и ако вие сте един от притежателите ѝ.
settings.transfer_form_title=Моля въведете следната информация за да потвърдите операцията: settings.transfer_form_title=Моля въведете следната информация за да потвърдите операцията:
settings.delete_notices_1=- Тази операция <strong>НЕ МОЖЕ</strong> да бъде отменена в последствие. settings.delete_notices_1=- Тази операция <strong>НЕ МОЖЕ</strong> да бъде отменена в последствие.
settings.delete_notices_2=- Тази операция ще изтрие всичко от това хранилище, включително Git данни, проблеми, коментари и достъпа на сътрудници. settings.delete_notices_2=- Тази операция ще изтрие всичко от това хранилище, включително Git данни, задачи, коментари и достъпа на сътрудници.
settings.delete_notices_fork_1=- Ако това хранилище е публично, всички негови разклонения ще останат независими след изтриването му. settings.delete_notices_fork_1=- Ако това хранилище е публично, всички негови разклонения ще останат независими след изтриването му.
settings.delete_notices_fork_2=- Ако това хранилище е частно, всички негови разклонения ще бъдат премахнати по време на изтриването. settings.delete_notices_fork_2=- Ако това хранилище е частно, всички негови разклонения ще бъдат премахнати по време на изтриването.
settings.delete_notices_fork_3=- Ако желаете да запазите всички разклонения след изтриването му, първо направете хранилището публично. settings.delete_notices_fork_3=- Ако желаете да запазите всички разклонения след изтриването му, първо направете хранилището публично.
settings.deletion_success=Repository has been deleted successfully! settings.deletion_success=Хранилището е изтрито успешно!
settings.update_settings_success=Настройките на хранилището са запазени успешно. settings.update_settings_success=Настройките на хранилището са запазени успешно.
settings.transfer_owner=Нов притежател settings.transfer_owner=Нов притежател
settings.make_transfer=Прехвърли settings.make_transfer=Прехвърли
@ -598,9 +608,9 @@ settings.hooks_desc=Уеб-куките много приличат на оби
settings.webhook_deletion=Изтрий уеб-кука settings.webhook_deletion=Изтрий уеб-кука
settings.webhook_deletion_desc=При изтриване на тази уеб-кука ще се премахне информацията за нея и цялата хронология на нейното изпращане. Желаете ли да продължите? settings.webhook_deletion_desc=При изтриване на тази уеб-кука ще се премахне информацията за нея и цялата хронология на нейното изпращане. Желаете ли да продължите?
settings.webhook_deletion_success=Уеб-куката е изтрита успешно! settings.webhook_deletion_success=Уеб-куката е изтрита успешно!
settings.webhook.test_delivery=Test Delivery settings.webhook.test_delivery=Тестово изпращане
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings settings.webhook.test_delivery_desc=Симулира тестово изпращане за тест на настройките на уеб-куката
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history. settings.webhook.test_delivery_success=Тестовата уеб-кука е добавена в опашката за изпращане. Може да отнеме няколко секунди преди да се появи в историята с доставени.
settings.webhook.request=Заявка settings.webhook.request=Заявка
settings.webhook.response=Отговор settings.webhook.response=Отговор
settings.webhook.headers=Заглавки settings.webhook.headers=Заглавки
@ -610,7 +620,7 @@ settings.githooks_desc=Git куките се изпълняват от Git. Ви
settings.githook_edit_desc=Ако куката е неактивна, ще бъде представено примерно съдържание. Ако оставите съдържанието празно, то тази кука ще бъде изключена. settings.githook_edit_desc=Ако куката е неактивна, ще бъде представено примерно съдържание. Ако оставите съдържанието празно, то тази кука ще бъде изключена.
settings.githook_name=Име на куката settings.githook_name=Име на куката
settings.githook_content=Съдържание на куката settings.githook_content=Съдържание на куката
settings.update_githook=Обнови куката settings.update_githook=Запази куката
settings.add_webhook_desc=Gogs ще изпрати <code>POST</code> заявка към указания URL адрес заедно с информация за събитието, което е настъпило. Също можете да укажете в какъв формат желаете да получите данните при задействане на куката (JSON, x-www-form-urlencoded, XML) и др. Допълнително описание можете да намерите в нашето <a target="_blank" href="%s">Ръководство за уеб-куки</a>. settings.add_webhook_desc=Gogs ще изпрати <code>POST</code> заявка към указания URL адрес заедно с информация за събитието, което е настъпило. Също можете да укажете в какъв формат желаете да получите данните при задействане на куката (JSON, x-www-form-urlencoded, XML) и др. Допълнително описание можете да намерите в нашето <a target="_blank" href="%s">Ръководство за уеб-куки</a>.
settings.payload_url=URL адрес на изпращане settings.payload_url=URL адрес на изпращане
settings.content_type=Тип на съдържанието settings.content_type=Тип на съдържанието
@ -629,13 +639,13 @@ settings.event_push_desc=Git предаване към хранилището
settings.active=Активна settings.active=Активна
settings.active_helper=Подробности относно събитието, което е задействало куката, също ще бъдат изпратени. settings.active_helper=Подробности относно събитието, което е задействало куката, също ще бъдат изпратени.
settings.add_hook_success=Новата уеб-кука е добавена успешно. settings.add_hook_success=Новата уеб-кука е добавена успешно.
settings.update_webhook=Обнови уеб-куката settings.update_webhook=Запази уеб-куката
settings.update_hook_success=Уеб-куката е запазена успешно. settings.update_hook_success=Уеб-куката е запазена успешно.
settings.delete_webhook=Изтрий уеб-куката settings.delete_webhook=Изтрий уеб-куката
settings.recent_deliveries=Последни изпращания settings.recent_deliveries=Последни изпращания
settings.hook_type=Тип на куката settings.hook_type=Тип на куката
settings.add_slack_hook_desc=Добавяне на интеграция със <a href="%s">Slack</a> във Вашето хранилище. settings.add_slack_hook_desc=Добавяне на интеграция със <a href="%s">Slack</a> във Вашето хранилище.
settings.slack_token=Токен settings.slack_token=API ключ
settings.slack_domain=Домейн settings.slack_domain=Домейн
settings.slack_channel=Канал settings.slack_channel=Канал
settings.deploy_keys=Ключове за внедряване settings.deploy_keys=Ключове за внедряване
@ -660,15 +670,15 @@ diff.stats_desc=променени са <strong>%d файла</strong>, в ко
diff.bin=BIN diff.bin=BIN
diff.view_file=Целия файл diff.view_file=Целия файл
release.releases=Издания release.releases=Версии
release.new_release=Ново издание release.new_release=Нова версия
release.draft=Чернови release.draft=Чернови
release.prerelease=Предварителни release.prerelease=Предварителни
release.stable=Стабилни release.stable=Стабилни
release.edit=редактиране release.edit=редактиране
release.ahead=<strong>%d</strong> ревизии на %s след това издание release.ahead=<strong>%d</strong> ревизии на %s след тази версия
release.source_code=Изходен код release.source_code=Изходен код
release.new_subheader=Публикувайте издания на всяка нова итерация. release.new_subheader=Публикувайте версия на всяка нова итерация.
release.edit_subheader=Подробният журнал на промените ще помогне на потребителите да разберат какви подобрения са направени. release.edit_subheader=Подробният журнал на промените ще помогне на потребителите да разберат какви подобрения са направени.
release.tag_name=Име на маркера release.tag_name=Име на маркера
release.target=Цел release.target=Цел
@ -678,17 +688,17 @@ release.content=Съдържание
release.write=Редактор release.write=Редактор
release.preview=Преглед release.preview=Преглед
release.loading=Зареждане... release.loading=Зареждане...
release.prerelease_desc=Това е предварително издание release.prerelease_desc=Това е предварителна версия
release.prerelease_helper=Ние ще отбележим, че това издание не е завършено за употреба. release.prerelease_helper=Ние ще отбележим, че тази версия не е готова за продукционна употреба.
release.cancel=Отказ release.cancel=Отказ
release.publish=Публикувай издание release.publish=Публикувай версия
release.save_draft=Запис на чернова release.save_draft=Запис на чернова
release.edit_release=Редактирай издание release.edit_release=Редактирай версия
release.delete_release=Изтриване на това издание release.delete_release=Изтриване на тази версия
release.deletion=Изтрий изданието release.deletion=Изтрий версията
release.deletion_desc=При изтриване на това издание ще се премахне съответния Git маркер. Желаете ли да продължите? release.deletion_desc=При изтриване на тази версия ще се премахне и съответния Git маркер. Желаете ли да продължите?
release.deletion_success=Изданието беше изтрито успешно! release.deletion_success=Версията беше изтрита успешно!
release.tag_name_already_exist=Издание с това име на маркер вече съществува. release.tag_name_already_exist=Версия с това име на маркер вече съществува.
release.downloads=Изтегляния release.downloads=Изтегляния
[org] [org]
@ -718,7 +728,7 @@ settings.options=Опции
settings.full_name=Пълно име settings.full_name=Пълно име
settings.website=Уебсайт settings.website=Уебсайт
settings.location=Локация settings.location=Локация
settings.update_settings=Обнови настройките settings.update_settings=Запази настройките
settings.update_setting_success=Настройките на организацията са запазени успешно. settings.update_setting_success=Настройките на организацията са запазени успешно.
settings.change_orgname_prompt=Този промяна ще засегне всички връзки сочещи към организацията. settings.change_orgname_prompt=Този промяна ще засегне всички връзки сочещи към организацията.
settings.update_avatar_success=Настройките на аватара на организацията са запазени успешно. settings.update_avatar_success=Настройките на аватара на организацията са запазени успешно.
@ -755,7 +765,7 @@ teams.no_desc=Този екип няма описание
teams.settings=Настройки teams.settings=Настройки
teams.owners_permission_desc=Притежателите имат пълен достъп до <strong>всички хранилища</strong> и имат <strong>права на администратори</strong> на организацията. teams.owners_permission_desc=Притежателите имат пълен достъп до <strong>всички хранилища</strong> и имат <strong>права на администратори</strong> на организацията.
teams.members=Участници в екипа teams.members=Участници в екипа
teams.update_settings=Обнови настройките teams.update_settings=Запази настройките
teams.delete_team=Изтриване на този екип teams.delete_team=Изтриване на този екип
teams.add_team_member=Добави участник в екипа teams.add_team_member=Добави участник в екипа
teams.delete_team_title=Изтрий екипа teams.delete_team_title=Изтрий екипа
@ -786,7 +796,7 @@ total=Общо: %d
dashboard.statistic=Статистика dashboard.statistic=Статистика
dashboard.operations=Операции dashboard.operations=Операции
dashboard.system_status=Наблюдение на системния статус dashboard.system_status=Наблюдение на системния статус
dashboard.statistic_info=Gogs базата данни има <b>%d</b> потребители, <b>%d</b> организации, <b>%d</b> публични ключове, <b>%d</b> хранилища, <b>%d</b> наблюдавания, <b>%d</b> харесвания, <b>%d</b> действия, <b>%d</b> достъпи, <b>%d</b> проблеми, <b>%d</b> коментари, <b>%d</b> социални регистрации, <b>%d</b> последователи, <b>%d</b> огледала, <b>%d</b> издания, <b>%d</b> източници за вписване, <b>%d</b> уеб-куки, <b>%d</b> етапи, <b>%d</b> етикети, <b>%d</b> задачи на куки, <b>%d</b> екипи, <b>%d</b> задачи при актуализация, <b>%d</b> прикачени файлове. dashboard.statistic_info=Gogs базата данни има <b>%d</b> потребители, <b>%d</b> организации, <b>%d</b> публични ключове, <b>%d</b> хранилища, <b>%d</b> наблюдавания, <b>%d</b> харесвания, <b>%d</b> действия, <b>%d</b> достъпи, <b>%d</b> задачи, <b>%d</b> коментари, <b>%d</b> социални регистрации, <b>%d</b> последователи, <b>%d</b> огледала, <b>%d</b> версии, <b>%d</b> начини на удостоверяване, <b>%d</b> уеб-куки, <b>%d</b> етапи, <b>%d</b> етикети, <b>%d</b> задачи на куки, <b>%d</b> екипи, <b>%d</b> задачи при актуализация, <b>%d</b> прикачени файлове.
dashboard.operation_name=Име на операцията dashboard.operation_name=Име на операцията
dashboard.operation_switch=Превключи dashboard.operation_switch=Превключи
dashboard.operation_run=Изпълни dashboard.operation_run=Изпълни
@ -845,17 +855,19 @@ users.created=Създаване
users.send_register_notify=Прати уведомление на потребителя при регистрация users.send_register_notify=Прати уведомление на потребителя при регистрация
users.new_success=Новият профил '%s' е добавен успешно. users.new_success=Новият профил '%s' е добавен успешно.
users.edit=Редакция users.edit=Редакция
users.auth_source=Източник за удостоверяване users.auth_source=Начин на удостоверяване
users.local=Локално users.local=Локално
users.auth_login_name=Потребителско име за удостоверяване users.auth_login_name=Потребителско име за вход
users.password_helper=Оставете празна ако не се променя. users.password_helper=Оставете празна ако не се променя.
users.update_profile_success=Профилът е запазен успешно. users.update_profile_success=Профилът е запазен успешно.
users.edit_account=Редактирай профил users.edit_account=Редактирай профил
users.max_repo_creation=Макс. брой хранилища
users.max_repo_creation_desc=(Задайте -1 за да се използва глобалния лимит)
users.is_activated=Този профил е активиран users.is_activated=Този профил е активиран
users.is_admin=Този профил има административни права users.is_admin=Този профил има административни права
users.allow_git_hook=Този профил има разрешение да създава Git куки users.allow_git_hook=Този профил има разрешение да създава Git куки
users.allow_import_local=Този профил има права за импорт на локални хранилища users.allow_import_local=Този профил има права за импорт на локални хранилища
users.update_profile=Обнови профила users.update_profile=Запази профила
users.delete_account=Изтрий този профил users.delete_account=Изтрий този профил
users.still_own_repo=Този профил притежава поне едно хранилище. Първо трябва да изтриете хранилището или да го прехвърлите на друг потребител. users.still_own_repo=Този профил притежава поне едно хранилище. Първо трябва да изтриете хранилището или да го прехвърлите на друг потребител.
users.still_has_org=Този профил участва в поне една организация. Първо трябва да напуснете или изтриете тези организации. users.still_has_org=Този профил участва в поне една организация. Първо трябва да напуснете или изтриете тези организации.
@ -872,10 +884,10 @@ repos.name=Име
repos.private=Частно repos.private=Частно
repos.watches=Наблюдавания repos.watches=Наблюдавания
repos.stars=Харесвания repos.stars=Харесвания
repos.issues=Проблеми repos.issues=Задачи
auths.auth_manage_panel=Управление на удостоверявания auths.auth_manage_panel=Управление на удостоверявания
auths.new=Добави нов източник за удостоверяване auths.new=Добави нов начин на удостоверяване
auths.name=Име auths.name=Име
auths.type=Тип auths.type=Тип
auths.enabled=Активно auths.enabled=Активно
@ -912,7 +924,7 @@ auths.edit=Редактирай настройки за удостоверява
auths.activated=Това удостоверяване е активно auths.activated=Това удостоверяване е активно
auths.new_success=Новото удостоверяване '%s' е добавено успешно. auths.new_success=Новото удостоверяване '%s' е добавено успешно.
auths.update_success=Настройките за удостоверяване са запазени успешно. auths.update_success=Настройките за удостоверяване са запазени успешно.
auths.update=Обнови настройки за удостоверяване auths.update=Запази настройки за удостоверяване
auths.delete=Изтриване на това удостоверяване auths.delete=Изтриване на това удостоверяване
auths.delete_auth_title=Изтрий удостоверяването auths.delete_auth_title=Изтрий удостоверяването
auths.delete_auth_desc=Това удостоверяване ще бъде изтрито. Желаете ли да продължите? auths.delete_auth_desc=Това удостоверяване ще бъде изтрито. Желаете ли да продължите?
@ -995,26 +1007,26 @@ monitor.start=Начален час
monitor.execute_time=Време за изпълнение monitor.execute_time=Време за изпълнение
notices.system_notice_list=Системни известия notices.system_notice_list=Системни известия
notices.view_detail_header=View Notice Detail notices.view_detail_header=Преглед на детайли на съобщение
notices.actions=Actions notices.actions=Действия
notices.select_all=Select All notices.select_all=Избери всички
notices.deselect_all=Deselect All notices.deselect_all=Без избрани
notices.inverse_selection=Inverse Selection notices.inverse_selection=Обърни избора
notices.delete_selected=Delete Selected notices.delete_selected=Изтрий избраните
notices.delete_all=Delete All Notices notices.delete_all=Изтрий всички съобщения
notices.type=Тип notices.type=Тип
notices.type_1=Хранилище notices.type_1=Хранилище
notices.desc=Описание notices.desc=Описание
notices.op=Oп. notices.op=Oп.
notices.delete_success=System notices have been deleted successfully. notices.delete_success=Системните съобщения са изтрити успешно.
[action] [action]
create_repo=създаде хранилище <a href="%s"> %s</a> create_repo=създаде хранилище <a href="%s"> %s</a>
rename_repo=преименува хранилище от <code>%[1]s</code> на <a href="%[2]s">%[3]s</a> rename_repo=преименува хранилище от <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
commit_repo=предаде към <a href="%[1]s/src/%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a> commit_repo=предаде към <a href="%[1]s/src/%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a>
create_issue=`отвори проблем <a href="%s/issues/%s">%s#%[2]s"</a>` create_issue=`отвори задача <a href="%s/issues/%s">%s#%[2]s"</a>`
create_pull_request=`създаде заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>` create_pull_request=`създаде заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`коментира проблем <a href="%s/issues/%s">%s#%[2]s"</a>` comment_issue=`коментира задача <a href="%s/issues/%s">%s#%[2]s"</a>`
merge_pull_request=`обедини заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>` merge_pull_request=`обедини заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=прехвърли хранилище <code>%s</code> към <a href="%s">%s</a> transfer_repo=прехвърли хранилище <code>%s</code> към <a href="%s">%s</a>
push_tag=предаде маркер <a href="%s/src/%s">%[2]s</a> към <a href="%[1]s">[3]s</a> push_tag=предаде маркер <a href="%s/src/%s">%[2]s</a> към <a href="%[1]s">[3]s</a>

28
conf/locale/locale_de-DE.ini

@ -28,6 +28,7 @@ organization=Organisation
mirror=Spiegel mirror=Spiegel
new_repo=Neues Repository new_repo=Neues Repository
new_migrate=Neue Migration new_migrate=Neue Migration
new_mirror=Neuer Spiegel
new_fork=Neues abgespaltetes Repository new_fork=Neues abgespaltetes Repository
new_org=Neue Organisation new_org=Neue Organisation
manage_org=Organisationen verwalten manage_org=Organisationen verwalten
@ -247,6 +248,7 @@ uid=Uid
public_profile=Öffentliches Profil public_profile=Öffentliches Profil
profile_desc=Deine E-Mail-Adresse ist öffentlich einsehbar und wird für accountspezifische Benachrichtigungen verwendet, sowie für alle web-basierten Funktionen, die über die Seite gemacht werden. profile_desc=Deine E-Mail-Adresse ist öffentlich einsehbar und wird für accountspezifische Benachrichtigungen verwendet, sowie für alle web-basierten Funktionen, die über die Seite gemacht werden.
password_username_disabled=Nicht-lokalen Benutzern ist es nicht erlaubt, ihren Usernamen zu ändern.
full_name=Vollständiger Name full_name=Vollständiger Name
website=Webseite website=Webseite
location=Standort location=Standort
@ -271,6 +273,7 @@ new_password=Neues Passwort
retype_new_password=Neues Passwort erneut eingeben retype_new_password=Neues Passwort erneut eingeben
password_incorrect=Aktuelles Passwort ist nicht korrekt. password_incorrect=Aktuelles Passwort ist nicht korrekt.
change_password_success=Passwort geändert. Du kannst dich jetzt mit deinem neuen Passwort anmelden. change_password_success=Passwort geändert. Du kannst dich jetzt mit deinem neuen Passwort anmelden.
password_change_disabled=Nicht-lokalen Benutzern ist es nicht erlaubt, ihr Passwort zu ändern.
emails=E-Mail-Adressen emails=E-Mail-Adressen
manage_emails=E-Mail-Adressen verwalten manage_emails=E-Mail-Adressen verwalten
@ -352,10 +355,13 @@ auto_init=Repository mit ausgewählten Dateien und Vorlagen initialisieren
create_repo=Repository erstellen create_repo=Repository erstellen
default_branch=Standard-Branch default_branch=Standard-Branch
mirror_interval=Spiegel-Intervall (in Stunden) mirror_interval=Spiegel-Intervall (in Stunden)
mirror_address=Spiegeladresse
mirror_address_desc=Bitte notwendige Benutzerangaben in die Adresse aufnehmen.
watchers=Beobachter watchers=Beobachter
stargazers=Sterngucker stargazers=Sterngucker
forks=Forks forks=Forks
form.reach_limit_of_creation=Der Besitzer hat die maximale Anzahl vo %d erstellbaren Repositorys erreicht.
form.name_reserved=Repository-Name '%s' ist bereits vergeben. form.name_reserved=Repository-Name '%s' ist bereits vergeben.
form.name_pattern_not_allowed=Repository-Namesmuster '%s' ist nicht zulässig. form.name_pattern_not_allowed=Repository-Namesmuster '%s' ist nicht zulässig.
@ -369,6 +375,7 @@ migrate.permission_denied=Ihnen fehlen die Rechte zum Importieren lokaler Reposi
migrate.invalid_local_path=Lokaler Pfad ist ungültig, er existiert nicht oder ist kein Ordner. migrate.invalid_local_path=Lokaler Pfad ist ungültig, er existiert nicht oder ist kein Ordner.
migrate.failed=Fehler bei Migration: %v migrate.failed=Fehler bei Migration: %v
mirror_from=spiegeln von
forked_from=Geforkt von forked_from=Geforkt von
fork_from_self=Sie können keine Repository forken, welche ihnen gehört! fork_from_self=Sie können keine Repository forken, welche ihnen gehört!
copy_link=Kopieren copy_link=Kopieren
@ -506,9 +513,9 @@ pulls.merged=Zusammengeführt
pulls.has_merged=Dieser Pull-Request wurde erfolgreich zusammengeführt! pulls.has_merged=Dieser Pull-Request wurde erfolgreich zusammengeführt!
pulls.data_broken=Die Daten dieser Pull-Anforderung sind defekt aufgrund des Löschens von Fork-Informationen. pulls.data_broken=Die Daten dieser Pull-Anforderung sind defekt aufgrund des Löschens von Fork-Informationen.
pulls.is_checking=Die Konfliktprüfung ist in Arbeit. Bitte aktualisiere die Seite in wenigen Momenten. pulls.is_checking=Die Konfliktprüfung ist in Arbeit. Bitte aktualisiere die Seite in wenigen Momenten.
pulls.can_auto_merge_desc=Du kannst eine Auto-Merge Operation auf diese Pull-Anforderung durchführen. pulls.can_auto_merge_desc=Diese Pull-Anforderung kann automatisch zusammengeführt werden.
pulls.cannot_auto_merge_desc=Es kann keine Auto-Merge Operation durchgeführt werden, da es Konflikte zwischen den Commits gibt. pulls.cannot_auto_merge_desc=Diese Pull-Anforderung kann nicht automatisch zusammengeführt werden, da es Konflikte gibt.
pulls.cannot_auto_merge_helper=Bitte benutze ein Kommandozeilentool, um den Konflikt zu lösen. pulls.cannot_auto_merge_helper=Bitte manuell zusammenführen um die Konflikte zu lösen.
pulls.merge_pull_request=Pull-Request zusammenführen pulls.merge_pull_request=Pull-Request zusammenführen
pulls.open_unmerged_pull_exists=`Du kannst die Pull-Anforderung nicht wiedereröffnen, da bereits eine offene Pull-Anforderung (#%d) aus dem selben Repository mit den gleichen Merge-Informationen existiert und auf das Merging wartet.` pulls.open_unmerged_pull_exists=`Du kannst die Pull-Anforderung nicht wiedereröffnen, da bereits eine offene Pull-Anforderung (#%d) aus dem selben Repository mit den gleichen Merge-Informationen existiert und auf das Merging wartet.`
@ -563,6 +570,9 @@ settings.update_settings=Einstellungen speichern
settings.change_reponame_prompt=Diese Änderung wirkt sich darauf aus, wie sich Links auf Repositories beziehen. settings.change_reponame_prompt=Diese Änderung wirkt sich darauf aus, wie sich Links auf Repositories beziehen.
settings.advanced_settings=Erweiterte Einstellungen settings.advanced_settings=Erweiterte Einstellungen
settings.wiki_desc=Wiki aktivieren um Leuten das Schreiben von Dokumenten zu ermöglichen settings.wiki_desc=Wiki aktivieren um Leuten das Schreiben von Dokumenten zu ermöglichen
settings.use_external_wiki=Benutze externes Wiki
settings.external_wiki_url=Externe Wiki URL
settings.external_wiki_url_desc=Besucher werden auf die URL umgeleitet, wenn sie auf den Tab klicken.
settings.issues_desc=Benutze eingebauten leichtgewichtigen Issue-Tracker settings.issues_desc=Benutze eingebauten leichtgewichtigen Issue-Tracker
settings.use_external_issue_tracker=Benutze externen Issue-Tracker settings.use_external_issue_tracker=Benutze externen Issue-Tracker
settings.tracker_url_format=URL-Format für externen Issu-Tracker settings.tracker_url_format=URL-Format für externen Issu-Tracker
@ -598,9 +608,9 @@ settings.hooks_desc=Webhooks erlauben es dir, externe Dienste zu informieren, we
settings.webhook_deletion=Webhook entfernen settings.webhook_deletion=Webhook entfernen
settings.webhook_deletion_desc=Das Löschen dieses Webhooks wird alle zugehörigen Informationen und den Übertragungsverlauf entfernen. Wirklich fortfahren? settings.webhook_deletion_desc=Das Löschen dieses Webhooks wird alle zugehörigen Informationen und den Übertragungsverlauf entfernen. Wirklich fortfahren?
settings.webhook_deletion_success=Webhook wurde erfolgreich entfernt! settings.webhook_deletion_success=Webhook wurde erfolgreich entfernt!
settings.webhook.test_delivery=Test Delivery settings.webhook.test_delivery=Auslieferungstest
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings settings.webhook.test_delivery_desc=Sende eine imitierte Push-Ereignis-Auslieferung um die Webhook-Einstellungen zu testen
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history. settings.webhook.test_delivery_success=Test-Webhook wurde zur Auslieferungswarteschlange hinzugefügt. Es kann einige Sekunden dauern, bevor es in der Auslieferungshistorie erscheint.
settings.webhook.request=Anfrage settings.webhook.request=Anfrage
settings.webhook.response=Rückmeldung settings.webhook.response=Rückmeldung
settings.webhook.headers=Kopfzeilen settings.webhook.headers=Kopfzeilen
@ -640,7 +650,7 @@ settings.slack_domain=Domain
settings.slack_channel=Kanal settings.slack_channel=Kanal
settings.deploy_keys=Deploy-Keys settings.deploy_keys=Deploy-Keys
settings.add_deploy_key=Deploy-Key hinzufügen settings.add_deploy_key=Deploy-Key hinzufügen
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys. settings.deploy_key_desc=Auslieferungs-Schlüssel hat nur lesenden Zugriff. Er ist nicht identisch mit dem persönlichen SSH-Schlüssel des Accounts.
settings.no_deploy_keys=Du hast noch keine Deploy-Schlüssel hinzugefügt. settings.no_deploy_keys=Du hast noch keine Deploy-Schlüssel hinzugefügt.
settings.title=Titel settings.title=Titel
settings.deploy_key_content=Inhalt settings.deploy_key_content=Inhalt
@ -851,6 +861,8 @@ users.auth_login_name=Authentifizierung-Loginnname
users.password_helper=Leer lassen um es unverändert zu lassen. users.password_helper=Leer lassen um es unverändert zu lassen.
users.update_profile_success=Kontoprofil wurde erfolgreich aktualisiert. users.update_profile_success=Kontoprofil wurde erfolgreich aktualisiert.
users.edit_account=Konto bearbeiten users.edit_account=Konto bearbeiten
users.max_repo_creation=Limit zum Erstellen von Repositorys
users.max_repo_creation_desc=(auf -1 setzen, um das globale Standardlimit zu verwenden)
users.is_activated=Dieses Konto ist aktiviert users.is_activated=Dieses Konto ist aktiviert
users.is_admin=Dieses Konto hat Administratorrechte users.is_admin=Dieses Konto hat Administratorrechte
users.allow_git_hook=Dieses Konto ist berechtigt, Git-Hooks zu erstellen users.allow_git_hook=Dieses Konto ist berechtigt, Git-Hooks zu erstellen
@ -1018,7 +1030,7 @@ comment_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> kommentiert`
merge_pull_request=`Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> zuammengeführt` merge_pull_request=`Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> zuammengeführt`
transfer_repo=hat Repository <code>%s</code> transferiert an <a href="%s">%s</a> transfer_repo=hat Repository <code>%s</code> transferiert an <a href="%s">%s</a>
push_tag=hat nach <a href="%s/src/%s">%[2]s</a> in <a href="%[1]s">%[3]s</a> gepusht push_tag=hat nach <a href="%s/src/%s">%[2]s</a> in <a href="%[1]s">%[3]s</a> gepusht
compare_commits=Zeige Vergleich dieser %d Commits compare_commits=Zeige Vergleich für diese %d Commits
[tool] [tool]
ago=vor ago=vor

17
conf/locale/locale_en-US.ini

@ -28,6 +28,7 @@ organization = Organization
mirror = Mirror mirror = Mirror
new_repo = New Repository new_repo = New Repository
new_migrate = New Migration new_migrate = New Migration
new_mirror = New Mirror
new_fork = New Fork Repository new_fork = New Fork Repository
new_org = New Organization new_org = New Organization
manage_org = Manage Organizations manage_org = Manage Organizations
@ -247,6 +248,7 @@ uid = Uid
public_profile = Public Profile public_profile = Public Profile
profile_desc = Your email address is public and will be used for any account related notifications, and any web based operations made via the site. profile_desc = Your email address is public and will be used for any account related notifications, and any web based operations made via the site.
password_username_disabled = Non-local type users are not allowed to change their username.
full_name = Full Name full_name = Full Name
website = Website website = Website
location = Location location = Location
@ -271,6 +273,7 @@ new_password = New Password
retype_new_password = Retype New Password retype_new_password = Retype New Password
password_incorrect = Current password is not correct. password_incorrect = Current password is not correct.
change_password_success = Your password was successfully changed. You can now sign using this new password. change_password_success = Your password was successfully changed. You can now sign using this new password.
password_change_disabled = Non-local type users are not allowed to change their password.
emails = Email Addresses emails = Email Addresses
manage_emails = Manage email addresses manage_emails = Manage email addresses
@ -358,6 +361,7 @@ watchers = Watchers
stargazers = Stargazers stargazers = Stargazers
forks = Forks forks = Forks
form.reach_limit_of_creation = The owner has reached maximum creation limit of %d repositories.
form.name_reserved = Repository name '%s' is reserved. form.name_reserved = Repository name '%s' is reserved.
form.name_pattern_not_allowed = Repository name pattern '%s' is not allowed. form.name_pattern_not_allowed = Repository name pattern '%s' is not allowed.
@ -509,9 +513,9 @@ pulls.merged = Merged
pulls.has_merged = This pull request has been merged successfully! pulls.has_merged = This pull request has been merged successfully!
pulls.data_broken = Data of this pull request has been broken due to deletion of fork information. pulls.data_broken = Data of this pull request has been broken due to deletion of fork information.
pulls.is_checking = The conflict checking is still in progress, please refresh page in few moments. pulls.is_checking = The conflict checking is still in progress, please refresh page in few moments.
pulls.can_auto_merge_desc = You can perform auto-merge operation on this pull request. pulls.can_auto_merge_desc = This pull request can be merged automatically.
pulls.cannot_auto_merge_desc = You can't perform auto-merge operation because there are conflicts between commits. pulls.cannot_auto_merge_desc = This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper = Please use command line tool to solve it. pulls.cannot_auto_merge_helper = Please merge manually in order to resolve the conflicts.
pulls.merge_pull_request = Merge Pull Request pulls.merge_pull_request = Merge Pull Request
pulls.open_unmerged_pull_exists = `You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.` pulls.open_unmerged_pull_exists = `You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
@ -566,6 +570,9 @@ settings.update_settings = Update Settings
settings.change_reponame_prompt = This change will affect how links relate to the repository. settings.change_reponame_prompt = This change will affect how links relate to the repository.
settings.advanced_settings = Advanced Settings settings.advanced_settings = Advanced Settings
settings.wiki_desc = Enable wiki to allow people write documents settings.wiki_desc = Enable wiki to allow people write documents
settings.use_external_wiki = Use external wiki
settings.external_wiki_url = External Wiki URL
settings.external_wiki_url_desc = Visitors will be redirected to URL when they click on the tab.
settings.issues_desc = Enable builtin lightweight issue tracker settings.issues_desc = Enable builtin lightweight issue tracker
settings.use_external_issue_tracker = Use external issue tracker settings.use_external_issue_tracker = Use external issue tracker
settings.tracker_url_format = External Issue Tracker URL Format settings.tracker_url_format = External Issue Tracker URL Format
@ -603,7 +610,7 @@ settings.webhook_deletion_desc = Delete this webhook will remove its information
settings.webhook_deletion_success = Webhook has been deleted successfully! settings.webhook_deletion_success = Webhook has been deleted successfully!
settings.webhook.test_delivery = Test Delivery settings.webhook.test_delivery = Test Delivery
settings.webhook.test_delivery_desc = Send a fake push event delivery to test your webhook settings settings.webhook.test_delivery_desc = Send a fake push event delivery to test your webhook settings
settings.webhook.test_delivery_success = Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history. settings.webhook.test_delivery_success = Test webhook has been added to delivery queue. It may take few seconds before it shows up in the delivery history.
settings.webhook.request = Request settings.webhook.request = Request
settings.webhook.response = Response settings.webhook.response = Response
settings.webhook.headers = Headers settings.webhook.headers = Headers
@ -854,6 +861,8 @@ users.auth_login_name = Authentication Login Name
users.password_helper = Leave it empty to remain unchanged. users.password_helper = Leave it empty to remain unchanged.
users.update_profile_success = Account profile has been updated successfully. users.update_profile_success = Account profile has been updated successfully.
users.edit_account = Edit Account users.edit_account = Edit Account
users.max_repo_creation = Maximum Repository Creation Limit
users.max_repo_creation_desc = (Set -1 to use global default limit)
users.is_activated = This account is activated users.is_activated = This account is activated
users.is_admin = This account has administrator permissions users.is_admin = This account has administrator permissions
users.allow_git_hook = This account has permissions to create Git hooks users.allow_git_hook = This account has permissions to create Git hooks

30
conf/locale/locale_es-ES.ini

@ -28,6 +28,7 @@ organization=Organización
mirror=Mirror mirror=Mirror
new_repo=Nuevo repositorio new_repo=Nuevo repositorio
new_migrate=Nueva Migración new_migrate=Nueva Migración
new_mirror=Nueva réplica
new_fork=Nuevo Fork del Repositorio new_fork=Nuevo Fork del Repositorio
new_org=Nueva organización new_org=Nueva organización
manage_org=Administrar organizaciones manage_org=Administrar organizaciones
@ -247,6 +248,7 @@ uid=UUID
public_profile=Perfil Público public_profile=Perfil Público
profile_desc=Tu correo electrónico es público y será usado para todas las notificaciones relacionadas con cualquier cuenta y cualquier operación hecha a través de la web. profile_desc=Tu correo electrónico es público y será usado para todas las notificaciones relacionadas con cualquier cuenta y cualquier operación hecha a través de la web.
password_username_disabled=Los usuarios que no son locales no tienen permitido cambiar su nombre de usuario.
full_name=Nombre Completo full_name=Nombre Completo
website=Página Web website=Página Web
location=Localización location=Localización
@ -271,6 +273,7 @@ new_password=Nueva contraseña
retype_new_password=Confirmar nueva contraseña retype_new_password=Confirmar nueva contraseña
password_incorrect=Contraseña actual incorrecta. password_incorrect=Contraseña actual incorrecta.
change_password_success=La contraseña se ha modificado correctamente. Ya puedes iniciar sesión con tu nueva contraseña. change_password_success=La contraseña se ha modificado correctamente. Ya puedes iniciar sesión con tu nueva contraseña.
password_change_disabled=Los usuarios que no son locales no tienen permitido cambiar su contraseña.
emails=Direcciones de correo electrónico emails=Direcciones de correo electrónico
manage_emails=Gestionar direcciones de correo electrónico manage_emails=Gestionar direcciones de correo electrónico
@ -352,10 +355,13 @@ auto_init=Inicializar los archivos seleccionados y plantillas de este repositori
create_repo=Crear Repositorio create_repo=Crear Repositorio
default_branch=Rama por defecto default_branch=Rama por defecto
mirror_interval=Intervalo de mirror(en horas) mirror_interval=Intervalo de mirror(en horas)
mirror_address=Dirección de la réplica
mirror_address_desc=Por favor, incluya las credenciales de usuario necesarias en la dirección.
watchers=Seguidores watchers=Seguidores
stargazers=Fans stargazers=Fans
forks=Forks forks=Forks
form.reach_limit_of_creation=El propietario ha alcanzado el límite máximo de %d repositorios creados.
form.name_reserved=El nombre del repositorio '%s' está reservado. form.name_reserved=El nombre del repositorio '%s' está reservado.
form.name_pattern_not_allowed=El patrón del nombre del repositorio '%s' no está permitido. form.name_pattern_not_allowed=El patrón del nombre del repositorio '%s' no está permitido.
@ -369,6 +375,7 @@ migrate.permission_denied=No te está permitido importar repositorios locales.
migrate.invalid_local_path=Rutal local inválida, no existe o no es un directorio. migrate.invalid_local_path=Rutal local inválida, no existe o no es un directorio.
migrate.failed=Migración fallida: %v migrate.failed=Migración fallida: %v
mirror_from=espejo de
forked_from=forked de forked_from=forked de
fork_from_self=Eres el propietario del repositorio, ¡no puedes hacer fork! fork_from_self=Eres el propietario del repositorio, ¡no puedes hacer fork!
copy_link=Copiar copy_link=Copiar
@ -506,9 +513,9 @@ pulls.merged=Fuisionado
pulls.has_merged=¡Este pull request se ha completado con éxito! pulls.has_merged=¡Este pull request se ha completado con éxito!
pulls.data_broken=Los datos de este pull request ya no están disponibles porque se ha eliminado la información del fork. pulls.data_broken=Los datos de este pull request ya no están disponibles porque se ha eliminado la información del fork.
pulls.is_checking=Se está procediendo a la búsqueda de conflictos, por favor actualice la página en unos momentos. pulls.is_checking=Se está procediendo a la búsqueda de conflictos, por favor actualice la página en unos momentos.
pulls.can_auto_merge_desc=Puede realizar la operación auto-fusionado en este pull request. pulls.can_auto_merge_desc=Este Pull Request puede ser fusionado automáticamente.
pulls.cannot_auto_merge_desc=No puede realizar la operación de auto-fusionado porque existen conflictos entre los commits. pulls.cannot_auto_merge_desc=Este Pull Request no puede ser fusionado automáticamente porque hay conflictos.
pulls.cannot_auto_merge_helper=Por favor use la línea de comandos para resolverlo. pulls.cannot_auto_merge_helper=Por favor, fusiona manualmente para resolver los conflictos.
pulls.merge_pull_request=Fusionar Pull Request pulls.merge_pull_request=Fusionar Pull Request
pulls.open_unmerged_pull_exists=`Usted no puede realizar la operación de reapertura porque en estos momentos existe una solicitud de pull request (#%d) para el mismo repositorio con la misma información que se encuentra a la espera de aprobación` pulls.open_unmerged_pull_exists=`Usted no puede realizar la operación de reapertura porque en estos momentos existe una solicitud de pull request (#%d) para el mismo repositorio con la misma información que se encuentra a la espera de aprobación`
@ -563,10 +570,13 @@ settings.update_settings=Actualizar Configuración
settings.change_reponame_prompt=Este cambio afectará a los enlaces al repositorio. settings.change_reponame_prompt=Este cambio afectará a los enlaces al repositorio.
settings.advanced_settings=Ajustes avanzados settings.advanced_settings=Ajustes avanzados
settings.wiki_desc=Habilitar la Wiki para que los colaboradores documenten settings.wiki_desc=Habilitar la Wiki para que los colaboradores documenten
settings.use_external_wiki=Usar Wiki externa
settings.external_wiki_url=URL externa de la Wiki
settings.external_wiki_url_desc=Los visitantes serán redireccionados a la URL cuando hagan click en la barra.
settings.issues_desc=Habilitar tracker ligero de incidencias settings.issues_desc=Habilitar tracker ligero de incidencias
settings.use_external_issue_tracker=Usar tracker externo de incidencias settings.use_external_issue_tracker=Usar tracker externo de incidencias
settings.tracker_url_format=Formato URL del tracker de incidencias externo settings.tracker_url_format=Formato URL del tracker de incidencias externo
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index. settings.tracker_url_format_desc=Puedes usar las plantillas <code>{user} {repo} {index}</code> para el nombre de usuario, nombre del repositorio e índice del issue.
settings.pulls_desc=Habilitar Pull Requests para aceptar contribuciones públicas settings.pulls_desc=Habilitar Pull Requests para aceptar contribuciones públicas
settings.danger_zone=Zona de Peligro settings.danger_zone=Zona de Peligro
settings.transfer=Transferir la Propiedad settings.transfer=Transferir la Propiedad
@ -598,9 +608,9 @@ settings.hooks_desc=Los Webhooks permiten a servicios externos recibir notificac
settings.webhook_deletion=Eliminar Webhook settings.webhook_deletion=Eliminar Webhook
settings.webhook_deletion_desc=Al borrar este webhook se eliminará su información y todo su historial. ¿Desea continuar? settings.webhook_deletion_desc=Al borrar este webhook se eliminará su información y todo su historial. ¿Desea continuar?
settings.webhook_deletion_success=¡Webhook eliminado con éxito! settings.webhook_deletion_success=¡Webhook eliminado con éxito!
settings.webhook.test_delivery=Test Delivery settings.webhook.test_delivery=Test de entrega
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings settings.webhook.test_delivery_desc=Enviar un falso evento Push de entrega para probar tus ajustes de webhook
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history. settings.webhook.test_delivery_success=Probar que los webhook han sido añadidos a la cola de entrega. Esto puede tomar algunos segundos antes de aparecer en el historial de entregas.
settings.webhook.request=Petición settings.webhook.request=Petición
settings.webhook.response=Respuesta settings.webhook.response=Respuesta
settings.webhook.headers=Encabezado settings.webhook.headers=Encabezado
@ -640,7 +650,7 @@ settings.slack_domain=Dominio
settings.slack_channel=Canal settings.slack_channel=Canal
settings.deploy_keys=Claves de Despliegue settings.deploy_keys=Claves de Despliegue
settings.add_deploy_key=Añadir Clave de Despliegue settings.add_deploy_key=Añadir Clave de Despliegue
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys. settings.deploy_key_desc=La clave de desarrollo tiene sólo acceso de lectura. No es igual que las claves SSH de las cuentas personales.
settings.no_deploy_keys=No has añadido ninguna clave de despliegue. settings.no_deploy_keys=No has añadido ninguna clave de despliegue.
settings.title=Título settings.title=Título
settings.deploy_key_content=Contenido settings.deploy_key_content=Contenido
@ -851,6 +861,8 @@ users.auth_login_name=Nombre de Inicio de Sesión de Autenticación
users.password_helper=Deje el campo vacío si no desea cambiar la contraseña. users.password_helper=Deje el campo vacío si no desea cambiar la contraseña.
users.update_profile_success=El perfil de la cuenta se ha actualizado correctamente. users.update_profile_success=El perfil de la cuenta se ha actualizado correctamente.
users.edit_account=Editar Cuenta users.edit_account=Editar Cuenta
users.max_repo_creation=Límite máximo de repositorios
users.max_repo_creation_desc=(Configura a -1 para usar el límite global por defecto)
users.is_activated=Esta cuenta está activada users.is_activated=Esta cuenta está activada
users.is_admin=Esta cuenta tiene permisos de administrador users.is_admin=Esta cuenta tiene permisos de administrador
users.allow_git_hook=Esta cuenta tiene permisos para crear hooks de Git users.allow_git_hook=Esta cuenta tiene permisos para crear hooks de Git
@ -1018,7 +1030,7 @@ comment_issue=`comentó en la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`fusionado pull request <a href="%s/pulls/%s">%s#%[2]s</a>` merge_pull_request=`fusionado pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=transfirió el repositorio <code>%s</code> a <a href="%s">%s</a> transfer_repo=transfirió el repositorio <code>%s</code> a <a href="%s">%s</a>
push_tag=hizo push del tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a> push_tag=hizo push del tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
compare_commits=Ver la comparación de estos %d commits compare_commits=Ver comparación de estos %d commits
[tool] [tool]
ago=hace ago=hace

18
conf/locale/locale_fr-FR.ini

@ -28,6 +28,7 @@ organization=Organisation
mirror=Miroir mirror=Miroir
new_repo=Nouveau Dépôt new_repo=Nouveau Dépôt
new_migrate=Nouvelle Migration new_migrate=Nouvelle Migration
new_mirror=Nouveau miroir
new_fork=Nouvel embranchement new_fork=Nouvel embranchement
new_org=Nouvelle Organisation new_org=Nouvelle Organisation
manage_org=Gérer les Organisations manage_org=Gérer les Organisations
@ -247,6 +248,7 @@ uid=ID d'Utilisateur
public_profile=Profil Public public_profile=Profil Public
profile_desc=Votre adresse e-mail est publique et sera utilisée pour les notifications relatives au compte, ainsi que pour toute opération Web effectuée via le site. profile_desc=Votre adresse e-mail est publique et sera utilisée pour les notifications relatives au compte, ainsi que pour toute opération Web effectuée via le site.
password_username_disabled=Les utilisateurs non-locaux n'ont pas le droit de modifier leur nom d'utilisateur.
full_name=Nom Complet full_name=Nom Complet
website=Site Web website=Site Web
location=Localisation location=Localisation
@ -271,6 +273,7 @@ new_password=Nouveau Mot de Passe
retype_new_password=Retapez le nouveau mot de passe retype_new_password=Retapez le nouveau mot de passe
password_incorrect=Mot de passe actuel incorrect. password_incorrect=Mot de passe actuel incorrect.
change_password_success=Mot de passe modifié avec succès. Vous pouvez à présent vous connecter avec le nouveau mot de passe. change_password_success=Mot de passe modifié avec succès. Vous pouvez à présent vous connecter avec le nouveau mot de passe.
password_change_disabled=Les utilisateurs non-locaux n'ont pas le droit de modifier leur mot de passe.
emails=Adresses E-mail emails=Adresses E-mail
manage_emails=Gérer les adresses e-mail manage_emails=Gérer les adresses e-mail
@ -352,10 +355,13 @@ auto_init=Initialiser ce dépôt avec le modèle et les fichiers sélectionnés
create_repo=Créer un dépôt create_repo=Créer un dépôt
default_branch=Branche par défaut default_branch=Branche par défaut
mirror_interval=Intervalle du miroir (heure) mirror_interval=Intervalle du miroir (heure)
mirror_address=Adresse du miroir
mirror_address_desc=Veuillez inclure les informations d'identification nécessaires dans l'adresse.
watchers=Observateurs watchers=Observateurs
stargazers=Stargazers stargazers=Stargazers
forks=Embranchements forks=Embranchements
form.reach_limit_of_creation=Le propriétaire a atteint le nombre maximal de %d dépôts créés.
form.name_reserved=Le nom de dépôt '%s' est réservé. form.name_reserved=Le nom de dépôt '%s' est réservé.
form.name_pattern_not_allowed=Motif '%s' interdit pour les noms de dépôt. form.name_pattern_not_allowed=Motif '%s' interdit pour les noms de dépôt.
@ -369,6 +375,7 @@ migrate.permission_denied=Vous n'êtes pas autorisé à importer des dépôts lo
migrate.invalid_local_path=Chemin local non valide, non existant ou n'étant pas un dossier. migrate.invalid_local_path=Chemin local non valide, non existant ou n'étant pas un dossier.
migrate.failed=Echec de migration: %v migrate.failed=Echec de migration: %v
mirror_from=miroir de
forked_from=scindé depuis forked_from=scindé depuis
fork_from_self=Vous nous ne pouvez pas scinder un dépôt que vous possédez déja ! fork_from_self=Vous nous ne pouvez pas scinder un dépôt que vous possédez déja !
copy_link=Copier copy_link=Copier
@ -506,9 +513,9 @@ pulls.merged=Fusionné
pulls.has_merged=Cette Pull Request a été fusionnée avec succès ! pulls.has_merged=Cette Pull Request a été fusionnée avec succès !
pulls.data_broken=Les données de cette demande de rattachement ont été compromise en raison de la suppression d'informations sur l'embranchement. pulls.data_broken=Les données de cette demande de rattachement ont été compromise en raison de la suppression d'informations sur l'embranchement.
pulls.is_checking=La recherche de conflits est toujours en cours, veuillez rafraichir la page dans quelques instants. pulls.is_checking=La recherche de conflits est toujours en cours, veuillez rafraichir la page dans quelques instants.
pulls.can_auto_merge_desc=Vous pouvez effectuer d'opération de fusion automatique sur cette demande de Pull Request. pulls.can_auto_merge_desc=Cette pull request peut être fusionnée automatiquement.
pulls.cannot_auto_merge_desc=Vous ne pouvez effectuer des opération de fusion automatique car il y a des conflits entre les Commits. pulls.cannot_auto_merge_desc=Cette pull request ne peut être fusionnée automatiquement à cause de conflits.
pulls.cannot_auto_merge_helper=Veuillez utiliser l'outil en ligne de commande pour le résoudre. pulls.cannot_auto_merge_helper=Fusionner manuellement afin de résoudre les conflits.
pulls.merge_pull_request=Fusionner la Pull Request pulls.merge_pull_request=Fusionner la Pull Request
pulls.open_unmerged_pull_exists=`Vous ne pouvez effectuer une réouverture car il y a déjà une pull-request ouverte (#%d) depuis le même dépôt avec les mêmes informations de fusion et est en attente de fusion.` pulls.open_unmerged_pull_exists=`Vous ne pouvez effectuer une réouverture car il y a déjà une pull-request ouverte (#%d) depuis le même dépôt avec les mêmes informations de fusion et est en attente de fusion.`
@ -563,6 +570,9 @@ settings.update_settings=Valider
settings.change_reponame_prompt=Ce changement affectera comment les liens sont reliés avec le dépôt. settings.change_reponame_prompt=Ce changement affectera comment les liens sont reliés avec le dépôt.
settings.advanced_settings=Paramètres Avancés settings.advanced_settings=Paramètres Avancés
settings.wiki_desc=Activer le wiki pour permettre l'écriture de documents settings.wiki_desc=Activer le wiki pour permettre l'écriture de documents
settings.use_external_wiki=Utiliser un wiki externe
settings.external_wiki_url=URL Wiki externe
settings.external_wiki_url_desc=Les visiteurs seront redirigés vers cette URL lorsqu'ils cliqueront sur l'onglet.
settings.issues_desc=Activer le bug-tracker léger intégré settings.issues_desc=Activer le bug-tracker léger intégré
settings.use_external_issue_tracker=Utiliser un bug-tracker externe settings.use_external_issue_tracker=Utiliser un bug-tracker externe
settings.tracker_url_format=Format d'URL du bug tracker settings.tracker_url_format=Format d'URL du bug tracker
@ -851,6 +861,8 @@ users.auth_login_name=Nom d'utilisateur d'authentification
users.password_helper=Laissez-le vide pour ne pas changer. users.password_helper=Laissez-le vide pour ne pas changer.
users.update_profile_success=Profil mis à jour avec succès. users.update_profile_success=Profil mis à jour avec succès.
users.edit_account=Modifier le Compte users.edit_account=Modifier le Compte
users.max_repo_creation=Nombre maximum de dépôts créés
users.max_repo_creation_desc=(Mettre à -1 pour utiliser la limite globale par défaut)
users.is_activated=Ce compte est activé users.is_activated=Ce compte est activé
users.is_admin=Ce compte possède un niveau d'accès administrateur users.is_admin=Ce compte possède un niveau d'accès administrateur
users.allow_git_hook=Ce compte dispose des autorisations pour créer des crochets de Git users.allow_git_hook=Ce compte dispose des autorisations pour créer des crochets de Git

20
conf/locale/locale_it-IT.ini

@ -28,6 +28,7 @@ organization=Organizzazione
mirror=Mirror mirror=Mirror
new_repo=Nuovo Repository new_repo=Nuovo Repository
new_migrate=Nuova Migrazione new_migrate=Nuova Migrazione
new_mirror=New Mirror
new_fork=Nuovo Fork Repository new_fork=Nuovo Fork Repository
new_org=Nuova organizzazione new_org=Nuova organizzazione
manage_org=Gestisci le organizzazioni manage_org=Gestisci le organizzazioni
@ -247,6 +248,7 @@ uid=Uid
public_profile=Profilo pubblico public_profile=Profilo pubblico
profile_desc=Il tuo indirizzo e-mail è pubblico e sarà usato per ogni notifica inerente al tuo account, e per qualsiasi operazione web effettuata attraverso il sito. profile_desc=Il tuo indirizzo e-mail è pubblico e sarà usato per ogni notifica inerente al tuo account, e per qualsiasi operazione web effettuata attraverso il sito.
password_username_disabled=Non-local type users are not allowed to change their username.
full_name=Nome Completo full_name=Nome Completo
website=Sito web website=Sito web
location=Posizione location=Posizione
@ -271,6 +273,7 @@ new_password=Nuova Password
retype_new_password=Re-inserisci la password retype_new_password=Re-inserisci la password
password_incorrect=La Password attuale non è corretta. password_incorrect=La Password attuale non è corretta.
change_password_success=La tua password è stata cambiata con successo. Ora puoi accedere usando la nuova password. change_password_success=La tua password è stata cambiata con successo. Ora puoi accedere usando la nuova password.
password_change_disabled=Non-local type users are not allowed to change their password.
emails=Indirizzi e-mail emails=Indirizzi e-mail
manage_emails=Gestisci indirizzi email manage_emails=Gestisci indirizzi email
@ -352,10 +355,13 @@ auto_init=Initialize this repository with selected files and template
create_repo=Crea Repository create_repo=Crea Repository
default_branch=Ramo (Branch) predefinito default_branch=Ramo (Branch) predefinito
mirror_interval=Intervallo Mirror (in ore) mirror_interval=Intervallo Mirror (in ore)
mirror_address=Mirror Address
mirror_address_desc=Please include necessary user credentials in the address.
watchers=Watchers watchers=Watchers
stargazers=Stargazers stargazers=Stargazers
forks=Forks forks=Forks
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
form.name_reserved=Il nome repository %s è riservato. form.name_reserved=Il nome repository %s è riservato.
form.name_pattern_not_allowed=La struttura del nome del repository %s non è consentita. form.name_pattern_not_allowed=La struttura del nome del repository %s non è consentita.
@ -369,6 +375,7 @@ migrate.permission_denied=You are not allowed to import local repositories.
migrate.invalid_local_path=Percorso locale non valido, non esiste o non è una cartella. migrate.invalid_local_path=Percorso locale non valido, non esiste o non è una cartella.
migrate.failed=Migration failed: %v migrate.failed=Migration failed: %v
mirror_from=mirror from
forked_from=forkato da forked_from=forkato da
fork_from_self=Non puoi forkare il tuo stesso repository! fork_from_self=Non puoi forkare il tuo stesso repository!
copy_link=Copia copy_link=Copia
@ -506,9 +513,9 @@ pulls.merged=Merged
pulls.has_merged=This pull request has been merged successfully! pulls.has_merged=This pull request has been merged successfully!
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information. pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments. pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request. pulls.can_auto_merge_desc=This pull request can be merged automatically.
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits. pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper=Please use command line tool to solve it. pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
pulls.merge_pull_request=Unisci Pull Request pulls.merge_pull_request=Unisci Pull Request
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.` pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
@ -563,6 +570,9 @@ settings.update_settings=Aggiorna Impostazioni
settings.change_reponame_prompt=This change will affect how links relate to the repository. settings.change_reponame_prompt=This change will affect how links relate to the repository.
settings.advanced_settings=Advanced Settings settings.advanced_settings=Advanced Settings
settings.wiki_desc=Enable wiki to allow people write documents settings.wiki_desc=Enable wiki to allow people write documents
settings.use_external_wiki=Use external wiki
settings.external_wiki_url=External Wiki URL
settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
settings.issues_desc=Enable builtin lightweight issue tracker settings.issues_desc=Enable builtin lightweight issue tracker
settings.use_external_issue_tracker=Use external issue tracker settings.use_external_issue_tracker=Use external issue tracker
settings.tracker_url_format=External Issue Tracker URL Format settings.tracker_url_format=External Issue Tracker URL Format
@ -851,6 +861,8 @@ users.auth_login_name=Authentication Login Name
users.password_helper=Leave it empty to remain unchanged. users.password_helper=Leave it empty to remain unchanged.
users.update_profile_success=Profilo dell'account aggiornato con successo. users.update_profile_success=Profilo dell'account aggiornato con successo.
users.edit_account=Modifica Account users.edit_account=Modifica Account
users.max_repo_creation=Maximum Repository Creation Limit
users.max_repo_creation_desc=(Set -1 to use global default limit)
users.is_activated=Questo account è attivato users.is_activated=Questo account è attivato
users.is_admin=Questo account ha permessi di amministratore users.is_admin=Questo account ha permessi di amministratore
users.allow_git_hook=Questo account ha il permesso di creare hooks di Git users.allow_git_hook=Questo account ha il permesso di creare hooks di Git
@ -1018,7 +1030,7 @@ comment_issue=`ha commentato il problema <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>` merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=ha trasferito il repository <code>%s</code> a <a href="%s">%s</a> transfer_repo=ha trasferito il repository <code>%s</code> a <a href="%s">%s</a>
push_tag=ha pushato il tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a> push_tag=ha pushato il tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
compare_commits=Vedi confronto per questi %d commit compare_commits=View comparison for these %d commits
[tool] [tool]
ago=fa ago=fa

60
conf/locale/locale_ja-JP.ini

@ -28,6 +28,7 @@ organization=組織
mirror=ミラー mirror=ミラー
new_repo=新しいリポジトリ new_repo=新しいリポジトリ
new_migrate=新しい移行 new_migrate=新しい移行
new_mirror=New Mirror
new_fork=新しいフォークのリポジトリ new_fork=新しいフォークのリポジトリ
new_org=新しい組織 new_org=新しい組織
manage_org=組織を管理 manage_org=組織を管理
@ -247,6 +248,7 @@ uid=Uid
public_profile=パブリック プロフィール public_profile=パブリック プロフィール
profile_desc=あなたのメールアドレスは公開され、任意のアカウント関連の通知に使用されます。また、Webベースの操作はサイトを介して行います。 profile_desc=あなたのメールアドレスは公開され、任意のアカウント関連の通知に使用されます。また、Webベースの操作はサイトを介して行います。
password_username_disabled=Non-local type users are not allowed to change their username.
full_name=フルネーム full_name=フルネーム
website=WEBサイト website=WEBサイト
location=ロケーション location=ロケーション
@ -271,6 +273,7 @@ new_password=新しいパスワード
retype_new_password=新しいパスワードを再入力します。 retype_new_password=新しいパスワードを再入力します。
password_incorrect=現在のパスワードが正しくありません。 password_incorrect=現在のパスワードが正しくありません。
change_password_success=パスワードが正常に変更されました。今すぐ新しいパスワード経由でサインインすることができます。 change_password_success=パスワードが正常に変更されました。今すぐ新しいパスワード経由でサインインすることができます。
password_change_disabled=Non-local type users are not allowed to change their password.
emails=E-mail アドレス emails=E-mail アドレス
manage_emails=E-mail アドレスを管理 manage_emails=E-mail アドレスを管理
@ -352,10 +355,13 @@ auto_init=選択されたファイルおよびテンプレートでリポジト
create_repo=リポジトリを作成 create_repo=リポジトリを作成
default_branch=デフォルトのブランチ default_branch=デフォルトのブランチ
mirror_interval=ミラー 間隔(時) mirror_interval=ミラー 間隔(時)
mirror_address=Mirror Address
mirror_address_desc=Please include necessary user credentials in the address.
watchers=ウォッチャー watchers=ウォッチャー
stargazers=Stargazers stargazers=Stargazers
forks=フォーク forks=フォーク
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
form.name_reserved=リポジトリ名 '%s' は予約されています。 form.name_reserved=リポジトリ名 '%s' は予約されています。
form.name_pattern_not_allowed=リポジトリ名のパターン '%s' は許可されていません。 form.name_pattern_not_allowed=リポジトリ名のパターン '%s' は許可されていません。
@ -367,8 +373,9 @@ migrate.clone_address=クローンアドレス
migrate.clone_address_desc=これは、HTTP/HTTPS/GIT URL またはローカル サーバー パスを設定できます。 migrate.clone_address_desc=これは、HTTP/HTTPS/GIT URL またはローカル サーバー パスを設定できます。
migrate.permission_denied=ローカル リポジトリをインポートすることはできません。 migrate.permission_denied=ローカル リポジトリをインポートすることはできません。
migrate.invalid_local_path=ローカルパスが無効です。存在しないかディレクトリではありません。 migrate.invalid_local_path=ローカルパスが無効です。存在しないかディレクトリではありません。
migrate.failed=Migration failed: %v migrate.failed=移行に失敗しました: %v
mirror_from=mirror from
forked_from=フォーク元 forked_from=フォーク元
fork_from_self=すでにあなたの所有しているリポジトリはフォークできません fork_from_self=すでにあなたの所有しているリポジトリはフォークできません
copy_link=コピー copy_link=コピー
@ -388,7 +395,7 @@ create_new_repo_command=コマンドラインで新しいリポジトリを作
push_exist_repo=コマンド ・ ラインから既存のリポジトリをプッシュ push_exist_repo=コマンド ・ ラインから既存のリポジトリをプッシュ
repo_is_empty=このリポジトリは空です、後で戻って来て下さい! repo_is_empty=このリポジトリは空です、後で戻って来て下さい!
code=Code code=コード
branch=ブランチ branch=ブランチ
tree=ツリー tree=ツリー
filter_branch_and_tag=ブランチまたはタグをフィルタリング filter_branch_and_tag=ブランチまたはタグをフィルタリング
@ -457,7 +464,7 @@ issues.next=次ページ
issues.open_title=オープン issues.open_title=オープン
issues.closed_title=クローズ issues.closed_title=クローズ
issues.num_comments=%d コメント issues.num_comments=%d コメント
issues.commented_at=`commented <a id="%[1]s" href="#%[1]s">%[2]s</a>` issues.commented_at=`コメント <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.no_content=まだコンテンツがありません issues.no_content=まだコンテンツがありません
issues.close_issue=閉じる issues.close_issue=閉じる
issues.close_comment_issue=コメントと閉じる issues.close_comment_issue=コメントと閉じる
@ -506,9 +513,9 @@ pulls.merged=マージされた
pulls.has_merged=このプルプルリクエストは正常にマージされました! pulls.has_merged=このプルプルリクエストは正常にマージされました!
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information. pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments. pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request. pulls.can_auto_merge_desc=This pull request can be merged automatically.
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits. pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper=それを解決するためにコマンド ライン ツールを使用してください。 pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
pulls.merge_pull_request=プルリクエストをマージします。 pulls.merge_pull_request=プルリクエストをマージします。
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.` pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
@ -541,7 +548,7 @@ wiki.welcome=Wiki へようこそ!
wiki.welcome_desc=Wiki is the place where you would like to document your project together and make it better. wiki.welcome_desc=Wiki is the place where you would like to document your project together and make it better.
wiki.create_first_page=最初のページを作成する。 wiki.create_first_page=最初のページを作成する。
wiki.page=ページ wiki.page=ページ
wiki.filter_page=Filter page wiki.filter_page=フィルターページ
wiki.new_page=新しいページを作成 wiki.new_page=新しいページを作成
wiki.default_commit_message=このアップデートについてメモを書く(オプション) wiki.default_commit_message=このアップデートについてメモを書く(オプション)
wiki.save_page=ページを保存 wiki.save_page=ページを保存
@ -561,11 +568,14 @@ settings.basic_settings=基本設定
settings.site=公式サイト settings.site=公式サイト
settings.update_settings=設定の更新 settings.update_settings=設定の更新
settings.change_reponame_prompt=この変更はリンクがリポジトリに関連付ける方法に影響します。 settings.change_reponame_prompt=この変更はリンクがリポジトリに関連付ける方法に影響します。
settings.advanced_settings=Advanced Settings settings.advanced_settings=拡張設定
settings.wiki_desc=Enable wiki to allow people write documents settings.wiki_desc=Enable wiki to allow people write documents
settings.use_external_wiki=Use external wiki
settings.external_wiki_url=External Wiki URL
settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
settings.issues_desc=Enable builtin lightweight issue tracker settings.issues_desc=Enable builtin lightweight issue tracker
settings.use_external_issue_tracker=Use external issue tracker settings.use_external_issue_tracker=外部課題トラッキングシステムを使用
settings.tracker_url_format=External Issue Tracker URL Format settings.tracker_url_format=外部課題トラッキングツール URLのフォーマット
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index. settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
settings.pulls_desc=Enable pull requests to accept public contributions settings.pulls_desc=Enable pull requests to accept public contributions
settings.danger_zone=危険地帯 settings.danger_zone=危険地帯
@ -577,7 +587,7 @@ settings.delete_desc=リポジトリを削除すると元に戻せません。
settings.transfer_notices_1=-新しい所有者が個人ユーザーの場合、あなたがアクセスできなくなります。 settings.transfer_notices_1=-新しい所有者が個人ユーザーの場合、あなたがアクセスできなくなります。
settings.transfer_notices_2=- You will conserve access if new owner is an organization and if you're one of the owners. settings.transfer_notices_2=- You will conserve access if new owner is an organization and if you're one of the owners.
settings.transfer_form_title=操作を確認するために、以下の情報を入力してください。 settings.transfer_form_title=操作を確認するために、以下の情報を入力してください。
settings.delete_notices_1=- This operation <strong>CANNOT</strong> be undone. settings.delete_notices_1=-この操作は<strong>元に戻せません</strong> 。
settings.delete_notices_2=- This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators. settings.delete_notices_2=- This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators.
settings.delete_notices_fork_1=- If this repository is public, all forks will be became independent after deletion. settings.delete_notices_fork_1=- If this repository is public, all forks will be became independent after deletion.
settings.delete_notices_fork_2=- If this repository is private, all forks will be removed at the same time. settings.delete_notices_fork_2=- If this repository is private, all forks will be removed at the same time.
@ -640,7 +650,7 @@ settings.slack_domain=ドメイン
settings.slack_channel=チャンネル settings.slack_channel=チャンネル
settings.deploy_keys=デプロイキー settings.deploy_keys=デプロイキー
settings.add_deploy_key=デプロイキーを追加 settings.add_deploy_key=デプロイキーを追加
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys. settings.deploy_key_desc=個人アカウントのSSHキーとは異なり、デプロイキーは読み取り専用アクセスとなります。
settings.no_deploy_keys=でプロキーは1つも追加されていません。 settings.no_deploy_keys=でプロキーは1つも追加されていません。
settings.title=タイトル settings.title=タイトル
settings.deploy_key_content=コンテント settings.deploy_key_content=コンテント
@ -669,7 +679,7 @@ release.edit=編集
release.ahead=このリリース以降 %s へ <strong>%d</strong> コミット release.ahead=このリリース以降 %s へ <strong>%d</strong> コミット
release.source_code=ソース コード release.source_code=ソース コード
release.new_subheader=Publish releases to iterate product. release.new_subheader=Publish releases to iterate product.
release.edit_subheader=Detailed change log can help users understand what has been improved. release.edit_subheader=詳細な変更ログは、ユーザーに何が改善されたかの理解を助けることができます。
release.tag_name=タグ名 release.tag_name=タグ名
release.target=ターゲット release.target=ターゲット
release.tag_helper=既存のタグを選択するか、新しいタグを作成し発行します。 release.tag_helper=既存のタグを選択するか、新しいタグを作成し発行します。
@ -721,7 +731,7 @@ settings.location=ロケーション
settings.update_settings=設定の更新 settings.update_settings=設定の更新
settings.update_setting_success=組織の設定が更新されました。 settings.update_setting_success=組織の設定が更新されました。
settings.change_orgname_prompt=This change will affect how links relate to the organization. settings.change_orgname_prompt=This change will affect how links relate to the organization.
settings.update_avatar_success=Organization avatar setting has been updated successfully. settings.update_avatar_success=組織のアバター画像が正常に更新されました。
settings.delete=組織を削除 settings.delete=組織を削除
settings.delete_account=この組織を削除 settings.delete_account=この組織を削除
settings.delete_prompt=操作はこの組織を完全に削除し、復旧<strong>できない</strong>! settings.delete_prompt=操作はこの組織を完全に削除し、復旧<strong>できない</strong>!
@ -796,7 +806,7 @@ dashboard.delete_inactivate_accounts=非アクティブのアカウントをす
dashboard.delete_inactivate_accounts_success=すべての非アクティブアカウントは正常に削除されました。 dashboard.delete_inactivate_accounts_success=すべての非アクティブアカウントは正常に削除されました。
dashboard.delete_repo_archives=リポジトリのすべてのアーカイブを削除 dashboard.delete_repo_archives=リポジトリのすべてのアーカイブを削除
dashboard.delete_repo_archives_success=リポジトリのすべてのアーカイブが正常に削除されました。 dashboard.delete_repo_archives_success=リポジトリのすべてのアーカイブが正常に削除されました。
dashboard.delete_missing_repos=Delete all repository records that lost Git files dashboard.delete_missing_repos=Gitファイルが失われたリポジトリのすべてのレコードを削除
dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully. dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully.
dashboard.git_gc_repos=リポジトリでのガベージコレクションを実行します。 dashboard.git_gc_repos=リポジトリでのガベージコレクションを実行します。
dashboard.git_gc_repos_success=すべてのリポジトリは正常にガベージ コレクションを行いました。 dashboard.git_gc_repos_success=すべてのリポジトリは正常にガベージ コレクションを行いました。
@ -843,7 +853,7 @@ users.admin=アドミン
users.repos=リポジトリ users.repos=リポジトリ
users.created=作成されました users.created=作成されました
users.send_register_notify=登録通知をユーザーに送信 users.send_register_notify=登録通知をユーザーに送信
users.new_success=New account '%s' has been created successfully. users.new_success=新規アカウント '%s' が正常に作成されました。
users.edit=編集 users.edit=編集
users.auth_source=認証ソース users.auth_source=認証ソース
users.local=ローカル users.local=ローカル
@ -851,6 +861,8 @@ users.auth_login_name=認証ログイン名
users.password_helper=それをそのまま空のままにします。 users.password_helper=それをそのまま空のままにします。
users.update_profile_success=アカウントのプロファイルが更新されました。 users.update_profile_success=アカウントのプロファイルが更新されました。
users.edit_account=アカウントの編集 users.edit_account=アカウントの編集
users.max_repo_creation=Maximum Repository Creation Limit
users.max_repo_creation_desc=(Set -1 to use global default limit)
users.is_activated=アカウントがアクティブされました users.is_activated=アカウントがアクティブされました
users.is_admin=このアカウントには管理者の権限を持つ users.is_admin=このアカウントには管理者の権限を持つ
users.allow_git_hook=このアカウントには Git のフックを作成する権限を持つ users.allow_git_hook=このアカウントには Git のフックを作成する権限を持つ
@ -995,13 +1007,13 @@ monitor.start=開始日時
monitor.execute_time=実行時間: monitor.execute_time=実行時間:
notices.system_notice_list=システム通知 notices.system_notice_list=システム通知
notices.view_detail_header=View Notice Detail notices.view_detail_header=お知らせの詳細を表示
notices.actions=Actions notices.actions=アクション
notices.select_all=Select All notices.select_all=全て選択
notices.deselect_all=Deselect All notices.deselect_all=すべて選択解除
notices.inverse_selection=Inverse Selection notices.inverse_selection=反転
notices.delete_selected=Delete Selected notices.delete_selected=選択項目を削除
notices.delete_all=Delete All Notices notices.delete_all=すべての通知を削除
notices.type=タイプ notices.type=タイプ
notices.type_1=リポジトリ notices.type_1=リポジトリ
notices.desc=説明 notices.desc=説明
@ -1018,7 +1030,7 @@ comment_issue=`問題 <a href="%s/issues/%s">%s#%[2]s</a> のコメント`
merge_pull_request=`プルリクエスト <a href="%s/pulls/%s"> %s[2]s</a>をマージしました` merge_pull_request=`プルリクエスト <a href="%s/pulls/%s"> %s[2]s</a>をマージしました`
transfer_repo=リポジトリ <code>%s</code> を <a href="%s">%s</a> へ転送しました transfer_repo=リポジトリ <code>%s</code> を <a href="%s">%s</a> へ転送しました
push_tag=<a href="%[1]s">%[3]s</a> に タグ <a href="%[1]s/src/%[2]s">%[2]s</a> をプッシュしました push_tag=<a href="%[1]s">%[3]s</a> に タグ <a href="%[1]s/src/%[2]s">%[2]s</a> をプッシュしました
compare_commits=これら %d のコミットの比較を閲覧する compare_commits=View comparison for these %d commits
[tool] [tool]
ago= ago=

20
conf/locale/locale_lv-LV.ini

@ -28,6 +28,7 @@ organization=Organizācija
mirror=Spogulis mirror=Spogulis
new_repo=Jauns repozitorijs new_repo=Jauns repozitorijs
new_migrate=Jauna migrācija new_migrate=Jauna migrācija
new_mirror=New Mirror
new_fork=Jauns atdalītais repozitorijs new_fork=Jauns atdalītais repozitorijs
new_org=Jauna organizācija new_org=Jauna organizācija
manage_org=Pārvaldīt organizācijas manage_org=Pārvaldīt organizācijas
@ -247,6 +248,7 @@ uid=Lietotāja ID
public_profile=Publiskais profils public_profile=Publiskais profils
profile_desc=Jūsu e-pasta adrese ir publiska un tiks izmantota, lai nosūtītju Jums paziņojumus, kas saistīti ar Jūsu kontu vai darbībām veiktām caur šo mājas lapu. profile_desc=Jūsu e-pasta adrese ir publiska un tiks izmantota, lai nosūtītju Jums paziņojumus, kas saistīti ar Jūsu kontu vai darbībām veiktām caur šo mājas lapu.
password_username_disabled=Non-local type users are not allowed to change their username.
full_name=Pilns vārds full_name=Pilns vārds
website=Mājas lapa website=Mājas lapa
location=Atrašanās vieta location=Atrašanās vieta
@ -271,6 +273,7 @@ new_password=Jauna parole
retype_new_password=Ievadīt paroli atkāroti retype_new_password=Ievadīt paroli atkāroti
password_incorrect=Ievadīta nepareiza pašreizējā parole. password_incorrect=Ievadīta nepareiza pašreizējā parole.
change_password_success=Parole tika veiksmīgi nomainīta. Tagad jūs varat pieraksītites, izmantojot jauno paroli. change_password_success=Parole tika veiksmīgi nomainīta. Tagad jūs varat pieraksītites, izmantojot jauno paroli.
password_change_disabled=Non-local type users are not allowed to change their password.
emails=E-pasta adreses emails=E-pasta adreses
manage_emails=Pārvaldīt e-pasta adreses manage_emails=Pārvaldīt e-pasta adreses
@ -352,10 +355,13 @@ auto_init=Inicializēt šo repozitoriju ar izvēlētajiem failiem un sagatavi
create_repo=Izveidot repozitoriju create_repo=Izveidot repozitoriju
default_branch=Noklusējuma atzars default_branch=Noklusējuma atzars
mirror_interval=Spoguļošanas intervāls (stundās) mirror_interval=Spoguļošanas intervāls (stundās)
mirror_address=Mirror Address
mirror_address_desc=Please include necessary user credentials in the address.
watchers=Novērotāji watchers=Novērotāji
stargazers=Zvaigžņdevēji stargazers=Zvaigžņdevēji
forks=Atdalītie repozitoriji forks=Atdalītie repozitoriji
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
form.name_reserved=Repozitorija nosaukums '%s' ir rezervēts. form.name_reserved=Repozitorija nosaukums '%s' ir rezervēts.
form.name_pattern_not_allowed=Repozitorija nosaukums '%s' nav atļauts. form.name_pattern_not_allowed=Repozitorija nosaukums '%s' nav atļauts.
@ -369,6 +375,7 @@ migrate.permission_denied=Jums nav tiesību importēt lokālu repozitoriju.
migrate.invalid_local_path=Nekorents lokālais ceļš, tas neeksistē vai nav direktorijs. migrate.invalid_local_path=Nekorents lokālais ceļš, tas neeksistē vai nav direktorijs.
migrate.failed=Migrācija neizdevās: %v migrate.failed=Migrācija neizdevās: %v
mirror_from=mirror from
forked_from=atdalīts no forked_from=atdalīts no
fork_from_self=Nav iespējams atdalīt repozitoriju, kuram esat īpašnieks! fork_from_self=Nav iespējams atdalīt repozitoriju, kuram esat īpašnieks!
copy_link=Kopēt copy_link=Kopēt
@ -506,9 +513,9 @@ pulls.merged=Sapludināts
pulls.has_merged=Šo izmaiņu pieprasījums tika veiksmīgi sapludināts! pulls.has_merged=Šo izmaiņu pieprasījums tika veiksmīgi sapludināts!
pulls.data_broken=Nepieejami izmaiņu pieprasījuma dati, jo dzēsta informācija no atdalītā repozitorija. pulls.data_broken=Nepieejami izmaiņu pieprasījuma dati, jo dzēsta informācija no atdalītā repozitorija.
pulls.is_checking=Notiek konfliktu pārbaude, mirkli uzgaidiet un atjaunojiet lapu. pulls.is_checking=Notiek konfliktu pārbaude, mirkli uzgaidiet un atjaunojiet lapu.
pulls.can_auto_merge_desc=Ir iespējams veikt automātisko sapludināšanas darbību šim izmaiņu pieprasījumam. pulls.can_auto_merge_desc=This pull request can be merged automatically.
pulls.cannot_auto_merge_desc=Nav iespējams veikt automātisko sapludināšanas darbību, jo starp revīzijām ir konflikti. pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper=Lūdzu, izmantojiet komandrindas rīku, lai to atrisinātu. pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
pulls.merge_pull_request=Izmaiņu pieprasījuma sapludināšana pulls.merge_pull_request=Izmaiņu pieprasījuma sapludināšana
pulls.open_unmerged_pull_exists=`Jūs nevarat veikt atkārtotas atvēršanas darbību, jo jau eksistē izmaiņu pieprasījums (#%d) no šī repozitorija ar tādu pašu sapludināšanas informāciju un gaida sapludināšanu.` pulls.open_unmerged_pull_exists=`Jūs nevarat veikt atkārtotas atvēršanas darbību, jo jau eksistē izmaiņu pieprasījums (#%d) no šī repozitorija ar tādu pašu sapludināšanas informāciju un gaida sapludināšanu.`
@ -563,6 +570,9 @@ settings.update_settings=Mainīt iestatījumus
settings.change_reponame_prompt=Šī izmaiņa ietekmēs saites, kas ir saistītas ar šo repozitoriju. settings.change_reponame_prompt=Šī izmaiņa ietekmēs saites, kas ir saistītas ar šo repozitoriju.
settings.advanced_settings=Advanced Settings settings.advanced_settings=Advanced Settings
settings.wiki_desc=Enable wiki to allow people write documents settings.wiki_desc=Enable wiki to allow people write documents
settings.use_external_wiki=Use external wiki
settings.external_wiki_url=External Wiki URL
settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
settings.issues_desc=Enable builtin lightweight issue tracker settings.issues_desc=Enable builtin lightweight issue tracker
settings.use_external_issue_tracker=Use external issue tracker settings.use_external_issue_tracker=Use external issue tracker
settings.tracker_url_format=External Issue Tracker URL Format settings.tracker_url_format=External Issue Tracker URL Format
@ -851,6 +861,8 @@ users.auth_login_name=Autentifikācijas pieteikšanās vārds
users.password_helper=Atstājiet tukšu, ja nevēlaties mainīt. users.password_helper=Atstājiet tukšu, ja nevēlaties mainīt.
users.update_profile_success=Konta profils tika veiksmīgi saglabāts. users.update_profile_success=Konta profils tika veiksmīgi saglabāts.
users.edit_account=Labot kontu users.edit_account=Labot kontu
users.max_repo_creation=Maximum Repository Creation Limit
users.max_repo_creation_desc=(Set -1 to use global default limit)
users.is_activated=Konts ir aktivizēts users.is_activated=Konts ir aktivizēts
users.is_admin=Šim kontam ir administratora piekļuves tiesības users.is_admin=Šim kontam ir administratora piekļuves tiesības
users.allow_git_hook=Šim kontam ir tiesības pievienot/labot Git āķus users.allow_git_hook=Šim kontam ir tiesības pievienot/labot Git āķus
@ -1018,7 +1030,7 @@ comment_issue=`pievienoja komentāru problēmai <a href="%s/issues/%s">%s#%[2]s<
merge_pull_request=`sapludināja izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>` merge_pull_request=`sapludināja izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="%s">%s</a> transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="%s">%s</a>
push_tag=pievienoja tagu <a href="%s/src/%s">%[2]s</a> repozitorijam <a href="%[1]s">%[3]s</a> push_tag=pievienoja tagu <a href="%s/src/%s">%[2]s</a> repozitorijam <a href="%[1]s">%[3]s</a>
compare_commits=Veikt salīdzināšanu starp šīm %d revīzijām compare_commits=View comparison for these %d commits
[tool] [tool]
ago=atpakaļ ago=atpakaļ

20
conf/locale/locale_nl-NL.ini

@ -28,6 +28,7 @@ organization=Organisatie
mirror=Spiegel mirror=Spiegel
new_repo=Nieuwe repositorie new_repo=Nieuwe repositorie
new_migrate=Nieuwe migratie new_migrate=Nieuwe migratie
new_mirror=New Mirror
new_fork=Nieuwe vork Repository new_fork=Nieuwe vork Repository
new_org=Nieuwe organisatie new_org=Nieuwe organisatie
manage_org=Beheer organisaties manage_org=Beheer organisaties
@ -247,6 +248,7 @@ uid=uid
public_profile=Openbaar profiel public_profile=Openbaar profiel
profile_desc=Uw e-mailadres is openbaar en zal gebruikt worden voor alle account gerelateerde berichtgevingen en bewerkingingen die via de website worden gedaan. profile_desc=Uw e-mailadres is openbaar en zal gebruikt worden voor alle account gerelateerde berichtgevingen en bewerkingingen die via de website worden gedaan.
password_username_disabled=Non-local type users are not allowed to change their username.
full_name=Volledige naam full_name=Volledige naam
website=Website website=Website
location=Locatie location=Locatie
@ -271,6 +273,7 @@ new_password=Nieuw wachtwoord
retype_new_password=Retype New Password retype_new_password=Retype New Password
password_incorrect=Huidig wachtwoord is niet correct. password_incorrect=Huidig wachtwoord is niet correct.
change_password_success=Wachtwoord is succesvol gewijzigd. U kunt nu met uw nieuwe wachtwoord inloggen. change_password_success=Wachtwoord is succesvol gewijzigd. U kunt nu met uw nieuwe wachtwoord inloggen.
password_change_disabled=Non-local type users are not allowed to change their password.
emails=E-mailadressen emails=E-mailadressen
manage_emails=E-mailadressen beheren manage_emails=E-mailadressen beheren
@ -352,10 +355,13 @@ auto_init=Initialiseer deze repositorie met de geselecteerde bestanden en sjablo
create_repo=Nieuwe Repositorie create_repo=Nieuwe Repositorie
default_branch=Standaard branch default_branch=Standaard branch
mirror_interval=Mirror interval(uur) mirror_interval=Mirror interval(uur)
mirror_address=Mirror Address
mirror_address_desc=Please include necessary user credentials in the address.
watchers=Watchers watchers=Watchers
stargazers=Stargazers stargazers=Stargazers
forks=Forks forks=Forks
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
form.name_reserved=Repositorienaam '%s' is gereserveerd. form.name_reserved=Repositorienaam '%s' is gereserveerd.
form.name_pattern_not_allowed=Repositorie naampatroon '%s' is niet toegestaan. form.name_pattern_not_allowed=Repositorie naampatroon '%s' is niet toegestaan.
@ -369,6 +375,7 @@ migrate.permission_denied=You are not allowed to import local repositories.
migrate.invalid_local_path=Ongeldig lokaal pad, het pad bestaat niet of het is geen map. migrate.invalid_local_path=Ongeldig lokaal pad, het pad bestaat niet of het is geen map.
migrate.failed=Migration failed: %v migrate.failed=Migration failed: %v
mirror_from=mirror from
forked_from=geforked van forked_from=geforked van
fork_from_self=U kunt geen repository forken die u al beheert! fork_from_self=U kunt geen repository forken die u al beheert!
copy_link=Kopieer copy_link=Kopieer
@ -506,9 +513,9 @@ pulls.merged=Merged
pulls.has_merged=This pull request has been merged successfully! pulls.has_merged=This pull request has been merged successfully!
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information. pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments. pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request. pulls.can_auto_merge_desc=This pull request can be merged automatically.
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits. pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper=Please use command line tool to solve it. pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
pulls.merge_pull_request=Samenvoegen van pull verzoek pulls.merge_pull_request=Samenvoegen van pull verzoek
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.` pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
@ -563,6 +570,9 @@ settings.update_settings=Instellingen bewerken
settings.change_reponame_prompt=This change will affect how links relate to the repository. settings.change_reponame_prompt=This change will affect how links relate to the repository.
settings.advanced_settings=Advanced Settings settings.advanced_settings=Advanced Settings
settings.wiki_desc=Enable wiki to allow people write documents settings.wiki_desc=Enable wiki to allow people write documents
settings.use_external_wiki=Use external wiki
settings.external_wiki_url=External Wiki URL
settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
settings.issues_desc=Enable builtin lightweight issue tracker settings.issues_desc=Enable builtin lightweight issue tracker
settings.use_external_issue_tracker=Use external issue tracker settings.use_external_issue_tracker=Use external issue tracker
settings.tracker_url_format=External Issue Tracker URL Format settings.tracker_url_format=External Issue Tracker URL Format
@ -851,6 +861,8 @@ users.auth_login_name=Authentication Login Name
users.password_helper=Leave it empty to remain unchanged. users.password_helper=Leave it empty to remain unchanged.
users.update_profile_success=Profiel is succesvol bijgewerkt. users.update_profile_success=Profiel is succesvol bijgewerkt.
users.edit_account=Bewerk account users.edit_account=Bewerk account
users.max_repo_creation=Maximum Repository Creation Limit
users.max_repo_creation_desc=(Set -1 to use global default limit)
users.is_activated=Dit account is geactiveerd users.is_activated=Dit account is geactiveerd
users.is_admin=Dit account heeft beheerdersrechten users.is_admin=Dit account heeft beheerdersrechten
users.allow_git_hook=Deze account beschikt over machtigingen voor het maken van Git haken users.allow_git_hook=Deze account beschikt over machtigingen voor het maken van Git haken
@ -1018,7 +1030,7 @@ comment_issue=`reactie op issue <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>` merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=repositorie verplaatst naar <code>%s</code> naar <a href="%s">%s</a> transfer_repo=repositorie verplaatst naar <code>%s</code> naar <a href="%s">%s</a>
push_tag=geduwd label <a href="%s/src/%s"> %[2]s</a> naar <a href="%[1]s"> %[3]s</a> push_tag=geduwd label <a href="%s/src/%s"> %[2]s</a> naar <a href="%[1]s"> %[3]s</a>
compare_commits=Weergave vergelijking voor deze %d commits compare_commits=View comparison for these %d commits
[tool] [tool]
ago=geleden ago=geleden

578
conf/locale/locale_pl-PL.ini

File diff suppressed because it is too large Load Diff

94
conf/locale/locale_pt-BR.ini

@ -28,6 +28,7 @@ organization=Organização
mirror=Espelho mirror=Espelho
new_repo=Novo Repositório new_repo=Novo Repositório
new_migrate=Nova Migração new_migrate=Nova Migração
new_mirror=New Mirror
new_fork=Novo Fork de Repositório new_fork=Novo Fork de Repositório
new_org=Nova Organização new_org=Nova Organização
manage_org=Gerenciar Organizações manage_org=Gerenciar Organizações
@ -247,6 +248,7 @@ uid=Uid
public_profile=Perfil Público public_profile=Perfil Público
profile_desc=Seu endereço de E-mail é publico e será usado para qualquer notificação relacionada à conta, e qualquer operação na web feita através do site. profile_desc=Seu endereço de E-mail é publico e será usado para qualquer notificação relacionada à conta, e qualquer operação na web feita através do site.
password_username_disabled=Non-local type users are not allowed to change their username.
full_name=Nome Completo full_name=Nome Completo
website=Site website=Site
location=Localização location=Localização
@ -271,6 +273,7 @@ new_password=Nova Senha
retype_new_password=Digite novamente a nova senha retype_new_password=Digite novamente a nova senha
password_incorrect=A senha atual não está correta. password_incorrect=A senha atual não está correta.
change_password_success=A senha está alterada com sucesso. Você pode agora entrar com a senha nova. change_password_success=A senha está alterada com sucesso. Você pode agora entrar com a senha nova.
password_change_disabled=Non-local type users are not allowed to change their password.
emails=Endereços de E-mail emails=Endereços de E-mail
manage_emails=Gerenciar endereços de e-mail manage_emails=Gerenciar endereços de e-mail
@ -352,10 +355,13 @@ auto_init=Inicializar este repositório com os arquivos selecionados e modelo
create_repo=Criar Repositório create_repo=Criar Repositório
default_branch=Branch padrão default_branch=Branch padrão
mirror_interval=Intervalo de Espelho (hora) mirror_interval=Intervalo de Espelho (hora)
mirror_address=Endereço do espelho
mirror_address_desc=Por favor, inclua as credenciais do usuário necessários no endereço.
watchers=Observadores watchers=Observadores
stargazers=Usuários que estrelaram stargazers=Usuários que estrelaram
forks=Forks forks=Forks
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
form.name_reserved=O nome de repositório '%s' não pode ser usado. form.name_reserved=O nome de repositório '%s' não pode ser usado.
form.name_pattern_not_allowed=Não é permitido usar o padrão '%s' para o nome de repositório. form.name_pattern_not_allowed=Não é permitido usar o padrão '%s' para o nome de repositório.
@ -369,6 +375,7 @@ migrate.permission_denied=Você não pode importar repositórios locais.
migrate.invalid_local_path=Caminho local inválido, não existe ou não é um diretório. migrate.invalid_local_path=Caminho local inválido, não existe ou não é um diretório.
migrate.failed=Migração falhou: %v migrate.failed=Migração falhou: %v
mirror_from=espelho de
forked_from=forkado de forked_from=forkado de
fork_from_self=Você não pode criar fork de um repositório que já é seu! fork_from_self=Você não pode criar fork de um repositório que já é seu!
copy_link=Copiar copy_link=Copiar
@ -388,7 +395,7 @@ create_new_repo_command=Criar um novo repositório na linha de comando
push_exist_repo=Push um repositório existente na linha de comando push_exist_repo=Push um repositório existente na linha de comando
repo_is_empty=Este repositório está vazio, por favor volte mais tarde! repo_is_empty=Este repositório está vazio, por favor volte mais tarde!
code=Code code=Código
branch=Branch branch=Branch
tree=Árvore tree=Árvore
filter_branch_and_tag=Filtrar branch ou tag filter_branch_and_tag=Filtrar branch ou tag
@ -506,9 +513,9 @@ pulls.merged=Merge realizado
pulls.has_merged=Este pull request foi mesclado com sucesso! pulls.has_merged=Este pull request foi mesclado com sucesso!
pulls.data_broken=Dados deste pull request foram quebrados devido à deleção de informação do fork. pulls.data_broken=Dados deste pull request foram quebrados devido à deleção de informação do fork.
pulls.is_checking=A verificação do conflito ainda está em progresso, por favor recarregue a página em instantes. pulls.is_checking=A verificação do conflito ainda está em progresso, por favor recarregue a página em instantes.
pulls.can_auto_merge_desc=Você pode realizar uma auto-mescla neste pull request. pulls.can_auto_merge_desc=This pull request can be merged automatically.
pulls.cannot_auto_merge_desc=Você não pode realizar uma auto-mescla porque há conflitos entre os commits. pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper=Por favor, utilize linha de comando para solucionar isto. pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
pulls.merge_pull_request=Merge Pull Request pulls.merge_pull_request=Merge Pull Request
pulls.open_unmerged_pull_exists=' Você não pode executar a operação de reabrir porque já existe uma solicitação de pull aberta (#%d) do mesmo repositório com as mesmas informações de merge e está esperando pelo merge.' pulls.open_unmerged_pull_exists=' Você não pode executar a operação de reabrir porque já existe uma solicitação de pull aberta (#%d) do mesmo repositório com as mesmas informações de merge e está esperando pelo merge.'
@ -537,20 +544,20 @@ milestones.deletion_desc=Excluir este marco removerá a informação dele em tod
milestones.deletion_success=Marco excluído com sucesso! milestones.deletion_success=Marco excluído com sucesso!
wiki=Wiki wiki=Wiki
wiki.welcome=Welcome to Wiki! wiki.welcome=Bem-vindo ao wiki!
wiki.welcome_desc=Wiki is the place where you would like to document your project together and make it better. wiki.welcome_desc=Wiki é o lugar onde você gostaria de documentar o seu projeto em conjunto e torná-lo melhor.
wiki.create_first_page=Create the first page wiki.create_first_page=Criar a primeira página
wiki.page=Page wiki.page=Página
wiki.filter_page=Filter page wiki.filter_page=Filtrar página
wiki.new_page=Create New Page wiki.new_page=Criar nova página
wiki.default_commit_message=Write a note about this update (optional). wiki.default_commit_message=Escrever um comentário sobre esta atualização (opcional).
wiki.save_page=Save Page wiki.save_page=Salvar página
wiki.last_commit_info=%s edited this page %s wiki.last_commit_info=%s editou esta página %s
wiki.edit_page_button=Edit wiki.edit_page_button=Editar
wiki.new_page_button=New Page wiki.new_page_button=Nova página
wiki.page_already_exists=Wiki page with same name already exists. wiki.page_already_exists=já existe uma página de wiki com o mesmo nome.
wiki.pages=Pages wiki.pages=Páginas
wiki.last_updated=Last updated %s wiki.last_updated=Última atualização %s
settings=Configurações settings=Configurações
settings.options=Opções settings.options=Opções
@ -561,13 +568,16 @@ settings.basic_settings=Configurações Básicas
settings.site=Site Oficial settings.site=Site Oficial
settings.update_settings=Configurações de Atualização settings.update_settings=Configurações de Atualização
settings.change_reponame_prompt=Este mudanças vai afetar os links para este repositório. settings.change_reponame_prompt=Este mudanças vai afetar os links para este repositório.
settings.advanced_settings=Advanced Settings settings.advanced_settings=Configurações avançadas
settings.wiki_desc=Enable wiki to allow people write documents settings.wiki_desc=Habilitar o wiki para permitir que as pessoas escrevam documentos
settings.issues_desc=Enable builtin lightweight issue tracker settings.use_external_wiki=Use external wiki
settings.use_external_issue_tracker=Use external issue tracker settings.external_wiki_url=External Wiki URL
settings.tracker_url_format=External Issue Tracker URL Format settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index. settings.issues_desc=Habilitar gerenciamento de "problemas" nativo
settings.pulls_desc=Enable pull requests to accept public contributions settings.use_external_issue_tracker=Usar issue tracker externo
settings.tracker_url_format=Formato de URL do issue tracker externo
settings.tracker_url_format_desc=Você pode usar o espaço reservado <code>{user} {repo} {index}</code> para o nome do usuário, índice de nome e a questão do repositório.
settings.pulls_desc=Habilitar pull requests para aceitar contribuições públicas
settings.danger_zone=Zona de Perigo settings.danger_zone=Zona de Perigo
settings.transfer=Transferir Propriedade settings.transfer=Transferir Propriedade
settings.transfer_desc=Transferir este repositório para outro usuário ou para uma organização onde você tem direitos de administrador. settings.transfer_desc=Transferir este repositório para outro usuário ou para uma organização onde você tem direitos de administrador.
@ -582,7 +592,7 @@ settings.delete_notices_2=- Esta operação irá apagar permanentemente o tudo d
settings.delete_notices_fork_1=- Se este repositório é público, todos os forks se tornarão independentes após a deleção. settings.delete_notices_fork_1=- Se este repositório é público, todos os forks se tornarão independentes após a deleção.
settings.delete_notices_fork_2=- Se este repositório é privado, todos os forks serão removidos imediatamente. settings.delete_notices_fork_2=- Se este repositório é privado, todos os forks serão removidos imediatamente.
settings.delete_notices_fork_3=- Se você deseja manter todos os forks, por favor muda a visibilidade do repositório para pública primeiro. settings.delete_notices_fork_3=- Se você deseja manter todos os forks, por favor muda a visibilidade do repositório para pública primeiro.
settings.deletion_success=Repository has been deleted successfully! settings.deletion_success=Repositório excluído com sucesso!
settings.update_settings_success=As opções do repositório foram atualizadas com sucesso. settings.update_settings_success=As opções do repositório foram atualizadas com sucesso.
settings.transfer_owner=Novo Dono settings.transfer_owner=Novo Dono
settings.make_transfer=Fazer Transferência settings.make_transfer=Fazer Transferência
@ -598,9 +608,9 @@ settings.hooks_desc=Hooks da web ou Webhooks permitem serviços externos serem n
settings.webhook_deletion=Deletar Webhook settings.webhook_deletion=Deletar Webhook
settings.webhook_deletion_desc=Deletar este Webhook vai remover sua informação e todo o histórico de entrega. Deseja continuar? settings.webhook_deletion_desc=Deletar este Webhook vai remover sua informação e todo o histórico de entrega. Deseja continuar?
settings.webhook_deletion_success=Webhook deletado com sucesso! settings.webhook_deletion_success=Webhook deletado com sucesso!
settings.webhook.test_delivery=Test Delivery settings.webhook.test_delivery=Entrega de teste
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings settings.webhook.test_delivery_desc=Enviar uma entrega de evento de push falso para testar suas configurações de webhook
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history. settings.webhook.test_delivery_success=O teste webhook foi adicionado para a fila de entrega. Pode demorar alguns segundos antes de ser exibido no histórico de entrega.
settings.webhook.request=Solicitação settings.webhook.request=Solicitação
settings.webhook.response=Resposta settings.webhook.response=Resposta
settings.webhook.headers=Cabeçalhos settings.webhook.headers=Cabeçalhos
@ -640,7 +650,7 @@ settings.slack_domain=Domínio
settings.slack_channel=Canal settings.slack_channel=Canal
settings.deploy_keys=Chaves de Deploy settings.deploy_keys=Chaves de Deploy
settings.add_deploy_key=Nova chave settings.add_deploy_key=Nova chave
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys. settings.deploy_key_desc=Chave de deploy só tem acesso somente leitura. Não é igual as chaves SSH de conta pessoal.
settings.no_deploy_keys=Você ainda não adicionou chaves para implantação de software. settings.no_deploy_keys=Você ainda não adicionou chaves para implantação de software.
settings.title=Título settings.title=Título
settings.deploy_key_content=Conteúdo da chave settings.deploy_key_content=Conteúdo da chave
@ -851,6 +861,8 @@ users.auth_login_name=Nome de login da autenticação
users.password_helper=Deixe em branco para não mudar. users.password_helper=Deixe em branco para não mudar.
users.update_profile_success=O perfil da conta foi atualizado com sucesso. users.update_profile_success=O perfil da conta foi atualizado com sucesso.
users.edit_account=Editar Conta users.edit_account=Editar Conta
users.max_repo_creation=Maximum Repository Creation Limit
users.max_repo_creation_desc=(Set -1 to use global default limit)
users.is_activated=Esta conta está ativada users.is_activated=Esta conta está ativada
users.is_admin=Esta conta tem permissões de administrador users.is_admin=Esta conta tem permissões de administrador
users.allow_git_hook=Esta conta tem permissões para criar hooks do Git users.allow_git_hook=Esta conta tem permissões para criar hooks do Git
@ -890,8 +902,8 @@ auths.bind_password=Vincular senha
auths.bind_password_helper=Atenção: Esta senha é armazenada em texto plano. Não use uma conta com muitos privilégios. auths.bind_password_helper=Atenção: Esta senha é armazenada em texto plano. Não use uma conta com muitos privilégios.
auths.user_base=Base de pesquisa do usuário auths.user_base=Base de pesquisa do usuário
auths.user_dn=Usuário do DN auths.user_dn=Usuário do DN
auths.attribute_username=Username attribute auths.attribute_username=Atributo nome de usuário
auths.attribute_username_placeholder=Leave empty to use sign-in form field value for user name. auths.attribute_username_placeholder=Deixe vazio para usar o valor do campo de formulário de entrada de nome de usuário.
auths.attribute_name=Atributo primeiro nome auths.attribute_name=Atributo primeiro nome
auths.attribute_surname=Atributo sobrenome auths.attribute_surname=Atributo sobrenome
auths.attribute_mail=Atributo e-mail auths.attribute_mail=Atributo e-mail
@ -995,18 +1007,18 @@ monitor.start=Hora de Início
monitor.execute_time=Tempo de Execução monitor.execute_time=Tempo de Execução
notices.system_notice_list=Sistema de Notificações notices.system_notice_list=Sistema de Notificações
notices.view_detail_header=View Notice Detail notices.view_detail_header=Ver detalhe do anúncio
notices.actions=Actions notices.actions=Ações
notices.select_all=Select All notices.select_all=Selecionar tudo
notices.deselect_all=Deselect All notices.deselect_all=Desmarcar tudo
notices.inverse_selection=Inverse Selection notices.inverse_selection=Seleção inversa
notices.delete_selected=Delete Selected notices.delete_selected=Apagar seleção
notices.delete_all=Delete All Notices notices.delete_all=Excluir todos os avisos
notices.type=Tipo notices.type=Tipo
notices.type_1=Repositório notices.type_1=Repositório
notices.desc=Descrição notices.desc=Descrição
notices.op=Op. notices.op=Op.
notices.delete_success=System notices have been deleted successfully. notices.delete_success=Avisos do sistema foram excluídos com sucesso.
[action] [action]
create_repo=repositório criado <a href="%s"> %s</a> create_repo=repositório criado <a href="%s"> %s</a>
@ -1018,7 +1030,7 @@ comment_issue='comentou sobre a questão <a href="%s/issues/%s">%s#%[2]s</a>'
merge_pull_request=`mesclou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>` merge_pull_request=`mesclou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=repositório transferido de <code>%s</code> para <a href="%s">%s</a> transfer_repo=repositório transferido de <code>%s</code> para <a href="%s">%s</a>
push_tag=Foi feito push na tag <a href="%s/src/%s">%[2]s</a> para <a href="%[1]s">%[3]s</a> push_tag=Foi feito push na tag <a href="%s/src/%s">%[2]s</a> para <a href="%[1]s">%[3]s</a>
compare_commits=Ver comparação desses %d commits compare_commits=View comparison for these %d commits
[tool] [tool]
ago=atrás ago=atrás

56
conf/locale/locale_ru-RU.ini

@ -28,6 +28,7 @@ organization=Организация
mirror=Зеркало mirror=Зеркало
new_repo=Новый репозиторий new_repo=Новый репозиторий
new_migrate=Новая Миграция new_migrate=Новая Миграция
new_mirror=New Mirror
new_fork=Новый проект из репозитория new_fork=Новый проект из репозитория
new_org=Новая Организация new_org=Новая Организация
manage_org=Управление Организацией manage_org=Управление Организацией
@ -38,7 +39,7 @@ your_profile=Ваш профиль
your_settings=Ваши настройки your_settings=Ваши настройки
news_feed=Лента новостей news_feed=Лента новостей
pull_requests=Пулл-реквесты pull_requests=Pull Requests
issues=Вопросы issues=Вопросы
cancel=Отмена cancel=Отмена
@ -247,6 +248,7 @@ uid=UID
public_profile=Открытый профиль public_profile=Открытый профиль
profile_desc=Адрес вашей электронной почты является публичным и будет использован для любых уведомлений, связанных с аккаунтом, а также для любых действий, совершенных через сайт. profile_desc=Адрес вашей электронной почты является публичным и будет использован для любых уведомлений, связанных с аккаунтом, а также для любых действий, совершенных через сайт.
password_username_disabled=Non-local type users are not allowed to change their username.
full_name=ФИО full_name=ФИО
website=Веб-сайт website=Веб-сайт
location=Местоположение location=Местоположение
@ -271,6 +273,7 @@ new_password=Новый пароль
retype_new_password=Подтверждение нового пароля retype_new_password=Подтверждение нового пароля
password_incorrect=Текущий пароль не правильный. password_incorrect=Текущий пароль не правильный.
change_password_success=Пароль сменен успешно. Теперь вы можете войти с новым паролем. change_password_success=Пароль сменен успешно. Теперь вы можете войти с новым паролем.
password_change_disabled=Non-local type users are not allowed to change their password.
emails=Адреса электронной почты emails=Адреса электронной почты
manage_emails=Управление адресами электронной почты manage_emails=Управление адресами электронной почты
@ -312,7 +315,7 @@ unbind=Отвязать
unbind_success=Социальная учетная запись отвязана. unbind_success=Социальная учетная запись отвязана.
manage_access_token=Управление Токенами Персонального Доступа manage_access_token=Управление Токенами Персонального Доступа
generate_new_token=Создать новый токен generate_new_token=Создать новый token
tokens_desc=Созданные вами токены могут использоваться для доступа к Gogs API. tokens_desc=Созданные вами токены могут использоваться для доступа к Gogs API.
new_token_desc=Пока что каждый токен будет иметь полный доступ к вашей учетной записи. new_token_desc=Пока что каждый токен будет иметь полный доступ к вашей учетной записи.
token_name=Имя маркера token_name=Имя маркера
@ -352,10 +355,13 @@ auto_init=Инициализировать этот репозиторий вы
create_repo=Создать репозиторий create_repo=Создать репозиторий
default_branch=Ветка по умолчанию default_branch=Ветка по умолчанию
mirror_interval=Интервал зеркалирования (час) mirror_interval=Интервал зеркалирования (час)
mirror_address=Mirror Address
mirror_address_desc=Please include necessary user credentials in the address.
watchers=Наблюдатели watchers=Наблюдатели
stargazers=Звездочеты stargazers=Звездочеты
forks=Форки forks=Форки
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
form.name_reserved=Имя репозитория '%s' зарезервировано. form.name_reserved=Имя репозитория '%s' зарезервировано.
form.name_pattern_not_allowed=Шаблон имени репозитория '%s' не допускается. form.name_pattern_not_allowed=Шаблон имени репозитория '%s' не допускается.
@ -369,6 +375,7 @@ migrate.permission_denied=У вас нет прав на импорт локал
migrate.invalid_local_path=Недопустимый локальный путь. Возможно он не существует или является не папкой. migrate.invalid_local_path=Недопустимый локальный путь. Возможно он не существует или является не папкой.
migrate.failed=Миграция не удалась: %v migrate.failed=Миграция не удалась: %v
mirror_from=mirror from
forked_from=форк от forked_from=форк от
fork_from_self=Вы не можете форкнуть репозитарий, так как Вы уже его владелец! fork_from_self=Вы не можете форкнуть репозитарий, так как Вы уже его владелец!
copy_link=Скопировать copy_link=Скопировать
@ -388,7 +395,7 @@ create_new_repo_command=Создать новый репозиторий из к
push_exist_repo=Отправить существующий репозиторий из командной строки push_exist_repo=Отправить существующий репозиторий из командной строки
repo_is_empty=Этот репозиторий пуст, пожалуйста, возвращайтесь позже! repo_is_empty=Этот репозиторий пуст, пожалуйста, возвращайтесь позже!
code=Code code=Код
branch=Ветка branch=Ветка
tree=Дерево tree=Дерево
filter_branch_and_tag=Фильтр по ветке или тегу filter_branch_and_tag=Фильтр по ветке или тегу
@ -506,9 +513,9 @@ pulls.merged=Слито
pulls.has_merged=Слияние этого пулл-реквеста успешно завершено! pulls.has_merged=Слияние этого пулл-реквеста успешно завершено!
pulls.data_broken=Содержимое этого пулл-реквеста было нарушено, вследствии удаления или клонирования информации. pulls.data_broken=Содержимое этого пулл-реквеста было нарушено, вследствии удаления или клонирования информации.
pulls.is_checking=Продолжается проверка конфликтов, пожалуйста обновите страницу несколько позже. pulls.is_checking=Продолжается проверка конфликтов, пожалуйста обновите страницу несколько позже.
pulls.can_auto_merge_desc=Вы можете провести операцию автоматического слияния для этого пулл-реквеста. pulls.can_auto_merge_desc=This pull request can be merged automatically.
pulls.cannot_auto_merge_desc=Вы не можете произвести операцию автоматического слияния, потому как существуют конфликты между коммитами. pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper=Используйте командную строку для решения этого. pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
pulls.merge_pull_request=Слить пулл-реквест pulls.merge_pull_request=Слить пулл-реквест
pulls.open_unmerged_pull_exists=`Вы не можете произвести операцию переоткрытия, потому что уже существует пулл-реквест (#%d) из этого же репозитория, с такими же параметрами слияния, который ожидает слияния.` pulls.open_unmerged_pull_exists=`Вы не можете произвести операцию переоткрытия, потому что уже существует пулл-реквест (#%d) из этого же репозитория, с такими же параметрами слияния, который ожидает слияния.`
@ -561,13 +568,16 @@ settings.basic_settings=Основные параметры
settings.site=Официальный сайт settings.site=Официальный сайт
settings.update_settings=Обновить настройки settings.update_settings=Обновить настройки
settings.change_reponame_prompt=Это изменение повлияет на отношения ссылок к этому репозиторию. settings.change_reponame_prompt=Это изменение повлияет на отношения ссылок к этому репозиторию.
settings.advanced_settings=Advanced Settings settings.advanced_settings=Расширенные настройки
settings.wiki_desc=Включить Вики, чтобы позволить людям ипсать документы settings.wiki_desc=Включить Вики, чтобы позволить людям ипсать документы
settings.use_external_wiki=Use external wiki
settings.external_wiki_url=External Wiki URL
settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
settings.issues_desc=Включить встроенную, легковесную систему отслеживания ошибок settings.issues_desc=Включить встроенную, легковесную систему отслеживания ошибок
settings.use_external_issue_tracker=Использовать внешнюю систему отслеживания ошибок settings.use_external_issue_tracker=Использовать внешнюю систему отслеживания ошибок
settings.tracker_url_format=Внешний формат ссылки системы отслеживания ошибок. settings.tracker_url_format=Внешний формат ссылки системы отслеживания ошибок.
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index. settings.tracker_url_format_desc=Вы можете использовать шаблон <code>{user} {repo} {index}</code> для имени пользователя, репозитория и номера обсуждения.
settings.pulls_desc=Enable pull requests to accept public contributions settings.pulls_desc=Включить публичные пулл-реквесты
settings.danger_zone=Опасная зона settings.danger_zone=Опасная зона
settings.transfer=Передать права собственности settings.transfer=Передать права собственности
settings.transfer_desc=Передать репозиторий другому пользователю или организации где у вас есть права администратора. settings.transfer_desc=Передать репозиторий другому пользователю или организации где у вас есть права администратора.
@ -593,7 +603,7 @@ settings.add_collaborator_success=Был добавлен новый соавт
settings.remove_collaborator_success=Соавтор был удален. settings.remove_collaborator_success=Соавтор был удален.
settings.search_user_placeholder=Поиск пользователя... settings.search_user_placeholder=Поиск пользователя...
settings.user_is_org_member=Пользователь является членом организации, члены которой не могут быть добавлены в качестве соавтора. settings.user_is_org_member=Пользователь является членом организации, члены которой не могут быть добавлены в качестве соавтора.
settings.add_webhook=Добавить веб-хук settings.add_webhook=Добавить Webhook
settings.hooks_desc=Webhooks позволяют внешним службам получать уведомления при возникновении определенных событий на Gogs. При возникновении указанных событий мы отправим запрос POST на каждый заданный вами URL. Узнать больше можно в нашем <a target="_blank" href="%s">Руководстве по Webhooks</a>. settings.hooks_desc=Webhooks позволяют внешним службам получать уведомления при возникновении определенных событий на Gogs. При возникновении указанных событий мы отправим запрос POST на каждый заданный вами URL. Узнать больше можно в нашем <a target="_blank" href="%s">Руководстве по Webhooks</a>.
settings.webhook_deletion=Удалить веб-хук settings.webhook_deletion=Удалить веб-хук
settings.webhook_deletion_desc=Удаление этого веб-хука приведет к удалению всей, связанной с ним, информации, включая историю. Хотите продолжить? settings.webhook_deletion_desc=Удаление этого веб-хука приведет к удалению всей, связанной с ним, информации, включая историю. Хотите продолжить?
@ -608,9 +618,9 @@ settings.webhook.payload=Содержимое запроса
settings.webhook.body=Тело ответа settings.webhook.body=Тело ответа
settings.githooks_desc=Git-хуки предоставляются Git самим по себе, вы можете изменять файлы поддерживаемых хуков из списка ниже чтобы выполнять внешние операции. settings.githooks_desc=Git-хуки предоставляются Git самим по себе, вы можете изменять файлы поддерживаемых хуков из списка ниже чтобы выполнять внешние операции.
settings.githook_edit_desc=Если хук не активен, будет подставлен пример содержимого. Пустое значение в этом поле приведет к отключению хука. settings.githook_edit_desc=Если хук не активен, будет подставлен пример содержимого. Пустое значение в этом поле приведет к отключению хука.
settings.githook_name=Название веб-хукa settings.githook_name=Название Hook'a
settings.githook_content=Перехватить содержание settings.githook_content=Перехватить содержание
settings.update_githook=Обновить хук settings.update_githook=Обновить Hook
settings.add_webhook_desc=Мы отправим запрос <code>POST</code> на указанный ниже URL с информацией о событиях. Можно также указать формат, в котором вы бы хотели получить данные (JSON, <code>x-www-form-urlencoded</code>, <em>и т.д.</em>). Дополнительную информацию можно найти в <a target="_blank" href="%s">Руководстве по Webhook</a>. settings.add_webhook_desc=Мы отправим запрос <code>POST</code> на указанный ниже URL с информацией о событиях. Можно также указать формат, в котором вы бы хотели получить данные (JSON, <code>x-www-form-urlencoded</code>, <em>и т.д.</em>). Дополнительную информацию можно найти в <a target="_blank" href="%s">Руководстве по Webhook</a>.
settings.payload_url=URL обработчика settings.payload_url=URL обработчика
settings.content_type=Тип содержимого settings.content_type=Тип содержимого
@ -618,7 +628,7 @@ settings.secret=Secret
settings.slack_username=Имя пользователя settings.slack_username=Имя пользователя
settings.slack_icon_url=URL иконки settings.slack_icon_url=URL иконки
settings.slack_color=Цвет settings.slack_color=Цвет
settings.event_desc=На какие события этот веб-хук должен срабатывать? settings.event_desc=На какие события этот webhook должен срабатывать?
settings.event_push_only=Просто <code>push</code> событие. settings.event_push_only=Просто <code>push</code> событие.
settings.event_send_everything=Мне нужно <strong>все</strong>. settings.event_send_everything=Мне нужно <strong>все</strong>.
settings.event_choose=Позвольте мне выбрать то, что нужно. settings.event_choose=Позвольте мне выбрать то, что нужно.
@ -628,14 +638,14 @@ settings.event_push=Push
settings.event_push_desc=Push в репозиторий settings.event_push_desc=Push в репозиторий
settings.active=Активен settings.active=Активен
settings.active_helper=Подробности о событии, вызвавшем срабатывание хука, также будут предоставлены. settings.active_helper=Подробности о событии, вызвавшем срабатывание хука, также будут предоставлены.
settings.add_hook_success=Был добавлен новый веб-хук. settings.add_hook_success=Был добавлен новый webhook.
settings.update_webhook=Обновление веб-хука settings.update_webhook=Обновление Webhook
settings.update_hook_success=Веб-хук обновлен. settings.update_hook_success=Webhook обновлен.
settings.delete_webhook=Удалить автоматическое обновление settings.delete_webhook=Удалить автоматическое обновление
settings.recent_deliveries=Недавние рассылки settings.recent_deliveries=Недавние рассылки
settings.hook_type=Тип перехватчика settings.hook_type=Тип перехватчика
settings.add_slack_hook_desc=Добавить интеграцию с <a href="%s">Slack</a> в ваш репозиторий. settings.add_slack_hook_desc=Добавить интеграцию с <a href="%s">Slack</a> в ваш репозиторий.
settings.slack_token=Токен settings.slack_token=Token
settings.slack_domain=Домен settings.slack_domain=Домен
settings.slack_channel=Канал settings.slack_channel=Канал
settings.deploy_keys=Ключи развертывания settings.deploy_keys=Ключи развертывания
@ -851,6 +861,8 @@ users.auth_login_name=Логин для авторизации
users.password_helper=Оставьте пустым, чтобы оставить без изменений. users.password_helper=Оставьте пустым, чтобы оставить без изменений.
users.update_profile_success=Профиль учетной записи обновлен успешно. users.update_profile_success=Профиль учетной записи обновлен успешно.
users.edit_account=Изменение учетной записи users.edit_account=Изменение учетной записи
users.max_repo_creation=Maximum Repository Creation Limit
users.max_repo_creation_desc=(Set -1 to use global default limit)
users.is_activated=Эта учетная запись активирована users.is_activated=Эта учетная запись активирована
users.is_admin=У этой учетной записи есть права администратора users.is_admin=У этой учетной записи есть права администратора
users.allow_git_hook=Пользователь имеет право создать Git перехватчик users.allow_git_hook=Пользователь имеет право создать Git перехватчик
@ -890,7 +902,7 @@ auths.bind_password=Привязать пароль
auths.bind_password_helper=Внимание: Этот пароль сохранен в небезопасном виде. Не используйте высоко-привилегированную учетную запись. auths.bind_password_helper=Внимание: Этот пароль сохранен в небезопасном виде. Не используйте высоко-привилегированную учетную запись.
auths.user_base=База для поиска пользователя auths.user_base=База для поиска пользователя
auths.user_dn=DN пользователя auths.user_dn=DN пользователя
auths.attribute_username=Username attribute auths.attribute_username=Атрибут username
auths.attribute_username_placeholder=Leave empty to use sign-in form field value for user name. auths.attribute_username_placeholder=Leave empty to use sign-in form field value for user name.
auths.attribute_name=Имя аттрибута auths.attribute_name=Имя аттрибута
auths.attribute_surname=Фамилия аттрибута auths.attribute_surname=Фамилия аттрибута
@ -995,18 +1007,18 @@ monitor.start=Момент начала
monitor.execute_time=Время выполнения monitor.execute_time=Время выполнения
notices.system_notice_list=Система уведомлений notices.system_notice_list=Система уведомлений
notices.view_detail_header=View Notice Detail notices.view_detail_header=Подробности уведомления
notices.actions=Действия notices.actions=Действия
notices.select_all=Выбрать всё notices.select_all=Выбрать всё
notices.deselect_all=Убрать выделение со всего notices.deselect_all=Убрать выделение со всего
notices.inverse_selection=Инверсия выделения notices.inverse_selection=Инверсия выделения
notices.delete_selected=Удалить выбранные notices.delete_selected=Удалить выбранные
notices.delete_all=Delete All Notices notices.delete_all=Удалить все уведомления
notices.type=Тип notices.type=Тип
notices.type_1=Репозиторий notices.type_1=Репозиторий
notices.desc=Описание notices.desc=Описание
notices.op=Op. notices.op=Op.
notices.delete_success=System notices have been deleted successfully. notices.delete_success=Системное уведомление успешно удалено.
[action] [action]
create_repo=создан репозиторий <a href="%s"> %s</a> create_repo=создан репозиторий <a href="%s"> %s</a>
@ -1018,7 +1030,7 @@ comment_issue=`прокомментировал(а) вопрос <a href="%s/iss
merge_pull_request=`слил пул реквест <a href="%s/pulls/%s">%s#%[2]s</a>` merge_pull_request=`слил пул реквест <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=перенес репозиторий <code>%s</code> в <a href="%s">%s</a> transfer_repo=перенес репозиторий <code>%s</code> в <a href="%s">%s</a>
push_tag=запушил тэг <a href="%s/src/%s">%[2]s</a> в <a href="%[1]s">%[3]s</a> push_tag=запушил тэг <a href="%s/src/%s">%[2]s</a> в <a href="%[1]s">%[3]s</a>
compare_commits=Просмотреть сравнение %d коммитов compare_commits=View comparison for these %d commits
[tool] [tool]
ago=назад ago=назад

20
conf/locale/locale_zh-CN.ini

@ -28,6 +28,7 @@ organization=组织
mirror=镜像 mirror=镜像
new_repo=创建新的仓库 new_repo=创建新的仓库
new_migrate=迁移外部仓库 new_migrate=迁移外部仓库
new_mirror=创建新的镜像
new_fork=创建新的派生仓库 new_fork=创建新的派生仓库
new_org=创建新的组织 new_org=创建新的组织
manage_org=管理我的组织 manage_org=管理我的组织
@ -247,6 +248,7 @@ uid=用户 ID
public_profile=公开信息 public_profile=公开信息
profile_desc=您的邮箱地址将会被公开,并被用于接收帐户的所有提醒和通知。 profile_desc=您的邮箱地址将会被公开,并被用于接收帐户的所有提醒和通知。
password_username_disabled=非本地类型的用户被禁止修改用户名。
full_name=自定义名称 full_name=自定义名称
website=个人网站 website=个人网站
location=所在地区 location=所在地区
@ -271,6 +273,7 @@ new_password=新的密码
retype_new_password=重新输入新的密码 retype_new_password=重新输入新的密码
password_incorrect=当前密码不正确! password_incorrect=当前密码不正确!
change_password_success=密码修改成功!您现在可以使用新的密码登录。 change_password_success=密码修改成功!您现在可以使用新的密码登录。
password_change_disabled=非本地类型的用户被禁止修改密码。
emails=邮箱地址 emails=邮箱地址
manage_emails=管理邮箱地址 manage_emails=管理邮箱地址
@ -352,10 +355,13 @@ auto_init=使用选定的文件和模板初始化仓库
create_repo=创建仓库 create_repo=创建仓库
default_branch=默认分支 default_branch=默认分支
mirror_interval=镜像同步周期(小时) mirror_interval=镜像同步周期(小时)
mirror_address=镜像地址
mirror_address_desc=请在镜像地址中写入必要的用户凭据信息。
watchers=关注者 watchers=关注者
stargazers=称赞者 stargazers=称赞者
forks=派生仓库 forks=派生仓库
form.reach_limit_of_creation=该用户已经达到允许创建 %d 个仓库的最大上限。
form.name_reserved=仓库名称 '%s' 是被保留的。 form.name_reserved=仓库名称 '%s' 是被保留的。
form.name_pattern_not_allowed=仓库名称不允许 '%s' 的格式。 form.name_pattern_not_allowed=仓库名称不允许 '%s' 的格式。
@ -369,6 +375,7 @@ migrate.permission_denied=您没有获得导入本地仓库的权限。
migrate.invalid_local_path=无效的本地路径,不存在或不是一个目录! migrate.invalid_local_path=无效的本地路径,不存在或不是一个目录!
migrate.failed=迁移失败:%v migrate.failed=迁移失败:%v
mirror_from=镜像自地址
forked_from=派生自 forked_from=派生自
fork_from_self=无法派生已经拥有的仓库! fork_from_self=无法派生已经拥有的仓库!
copy_link=复制链接 copy_link=复制链接
@ -506,9 +513,9 @@ pulls.merged=已合并
pulls.has_merged=该合并请求已经成功合并! pulls.has_merged=该合并请求已经成功合并!
pulls.data_broken=该合并请求的数据由于派生仓库的相关信息被删除而被破坏。 pulls.data_broken=该合并请求的数据由于派生仓库的相关信息被删除而被破坏。
pulls.is_checking=该合并请求正在进行冲突检查,请稍后再刷新页面。 pulls.is_checking=该合并请求正在进行冲突检查,请稍后再刷新页面。
pulls.can_auto_merge_desc=您可以实现该合并请求的自动合并操作。 pulls.can_auto_merge_desc=该合并请求可以进行自动合并操作。
pulls.cannot_auto_merge_desc=因为代码提交存在冲突,您无法对该合并请求执行自动合并操作。 pulls.cannot_auto_merge_desc=该合并请求存在冲突,无法进行自动合并操作。
pulls.cannot_auto_merge_helper=使用命令行工具来解决冲突。 pulls.cannot_auto_merge_helper=手动拉取代码变更以解决冲突。
pulls.merge_pull_request=合并请求 pulls.merge_pull_request=合并请求
pulls.open_unmerged_pull_exists=`由于已经存在来自相同仓库和合并信息的未合并请求(#%d),您无法执行重新开启操作。` pulls.open_unmerged_pull_exists=`由于已经存在来自相同仓库和合并信息的未合并请求(#%d),您无法执行重新开启操作。`
@ -563,6 +570,9 @@ settings.update_settings=更新仓库设置
settings.change_reponame_prompt=该操作将会影响到所有与该仓库有关的链接 settings.change_reponame_prompt=该操作将会影响到所有与该仓库有关的链接
settings.advanced_settings=高级设置 settings.advanced_settings=高级设置
settings.wiki_desc=启用 Wiki 以允许用户协作文档 settings.wiki_desc=启用 Wiki 以允许用户协作文档
settings.use_external_wiki=使用外部 Wiki
settings.external_wiki_url=外部 Wiki 链接
settings.external_wiki_url_desc=当访问者单击分页标签时,将会被重定向到该链接。
settings.issues_desc=启用内置的轻量级工单管理系统 settings.issues_desc=启用内置的轻量级工单管理系统
settings.use_external_issue_tracker=使用外部的工单管理系统 settings.use_external_issue_tracker=使用外部的工单管理系统
settings.tracker_url_format=外部工单管理系统的 URL 格式 settings.tracker_url_format=外部工单管理系统的 URL 格式
@ -851,6 +861,8 @@ users.auth_login_name=认证登录名称
users.password_helper=将值留空使其保持不变。 users.password_helper=将值留空使其保持不变。
users.update_profile_success=该用户信息更新成功! users.update_profile_success=该用户信息更新成功!
users.edit_account=编辑用户信息 users.edit_account=编辑用户信息
users.max_repo_creation=最大允许创建仓库数量
users.max_repo_creation_desc=(设置为 -1 表示使用全局默认值)
users.is_activated=该用户已被激活 users.is_activated=该用户已被激活
users.is_admin=该用户具有管理员权限 users.is_admin=该用户具有管理员权限
users.allow_git_hook=该用户具有创建 Git 钩子的权限 users.allow_git_hook=该用户具有创建 Git 钩子的权限
@ -1018,7 +1030,7 @@ comment_issue=`评论了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`合并了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>` merge_pull_request=`合并了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=将仓库 <code>%s</code> 转移至 <a href="%s">%s</a> transfer_repo=将仓库 <code>%s</code> 转移至 <a href="%s">%s</a>
push_tag=推送了标签 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a> push_tag=推送了标签 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_commits=查看 %d 次提交的内容对比 compare_commits=对比 %d 次代码提交
[tool] [tool]
ago=之前 ago=之前

366
conf/locale/locale_zh-HK.ini

@ -28,6 +28,7 @@ organization=組織
mirror=鏡像 mirror=鏡像
new_repo=創建新的倉庫 new_repo=創建新的倉庫
new_migrate=遷移外部倉庫 new_migrate=遷移外部倉庫
new_mirror=New Mirror
new_fork=新的派生倉庫 new_fork=新的派生倉庫
new_org=創建新的組織 new_org=創建新的組織
manage_org=管理我的組織 manage_org=管理我的組織
@ -53,8 +54,8 @@ code=程式碼
[install] [install]
install=安裝頁面 install=安裝頁面
title=首次執行安裝程序 title=首次執行安裝程序
docker_helper=If you're running Gogs inside Docker, please read <a target="_blank" href="%s">Guidelines</a> carefully before you change anything in this page! docker_helper=如果您正在使用 Docker 容器運行 Gogs,請務必先仔細閱讀 <a target="_blank" href="%s">官方文檔</a> 後再對本頁面進行填寫。
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB. requite_db_desc=Gogs 要求安裝 MySQL、PostgreSQL、SQLite3 或 TiDB。
db_title=數據庫設置 db_title=數據庫設置
db_type=數據庫類型 db_type=數據庫類型
host=數據庫主機 host=數據庫主機
@ -64,11 +65,11 @@ db_name=數據庫名稱
db_helper=如果您使用 MySQL,請使用 INNODB 引擎以及 utf8_general_ci 字符集。 db_helper=如果您使用 MySQL,請使用 INNODB 引擎以及 utf8_general_ci 字符集。
ssl_mode=SSL 模式 ssl_mode=SSL 模式
path=數據庫文件路徑 path=數據庫文件路徑
sqlite_helper=The file path of SQLite3 or TiDB database. sqlite_helper=SQLite3 或 TiDB 的數據庫路徑。
err_empty_db_path=SQLite3 or TiDB database path cannot be empty. err_empty_db_path=SQLite3 或 TiDB 的數據庫路徑不能為空。
err_invalid_tidb_name=TiDB database name does not allow characters "." and "-". err_invalid_tidb_name=TiDB 數據庫名稱不允許包含字符 "." 或 "-" 。
no_admin_and_disable_registration=You cannot disable registration without creating an admin account. no_admin_and_disable_registration=您不能夠在未創建管理員用戶的情況下禁止註冊。
err_empty_admin_password=Admin password cannot be empty. err_empty_admin_password=管理員密碼不能為空。
general_title=應用基本設置 general_title=應用基本設置
app_name=應用名稱 app_name=應用名稱
@ -102,8 +103,8 @@ disable_gravatar=禁用 Gravatar 服務
disable_gravatar_popup=禁用 Gravatar 和自定義源,僅使用由用戶上傳或默認的頭像。 disable_gravatar_popup=禁用 Gravatar 和自定義源,僅使用由用戶上傳或默認的頭像。
disable_registration=禁止用戶自主註冊 disable_registration=禁止用戶自主註冊
disable_registration_popup=禁止用戶自主註冊功能,只有管理員可以添加帳號。 disable_registration_popup=禁止用戶自主註冊功能,只有管理員可以添加帳號。
enable_captcha=Enable Captcha enable_captcha=啟用驗證碼服務
enable_captcha_popup=Require validate captcha for user self-registration. enable_captcha_popup=要求在用戶註冊時輸入驗證碼
require_sign_in_view=啓用登錄訪問限制 require_sign_in_view=啓用登錄訪問限制
require_sign_in_view_popup=只有已登錄的用戶才能夠訪問頁面,否則將只能看到登錄或註冊頁面。 require_sign_in_view_popup=只有已登錄的用戶才能夠訪問頁面,否則將只能看到登錄或註冊頁面。
admin_setting_desc=創建管理員帳號並不是必須的,因為 ID=1 的用戶將自動獲得管理員權限。 admin_setting_desc=創建管理員帳號並不是必須的,因為 ID=1 的用戶將自動獲得管理員權限。
@ -111,7 +112,7 @@ admin_title=管理員帳號設置
admin_name=管理員用戶名 admin_name=管理員用戶名
admin_password=管理員密碼 admin_password=管理員密碼
confirm_password=確認密碼 confirm_password=確認密碼
admin_email=Admin Email admin_email=管理員郵箱
install_gogs=立即安裝 install_gogs=立即安裝
test_git_failed=無法識別 'git' 命令:%v test_git_failed=無法識別 'git' 命令:%v
sqlite3_not_available=您所使用的發行版本不支持 SQLite3,請從 %s 下載官方構建版,而不是 gobuild 版本。 sqlite3_not_available=您所使用的發行版本不支持 SQLite3,請從 %s 下載官方構建版,而不是 gobuild 版本。
@ -160,11 +161,11 @@ reset_password_helper=單擊此處重置密碼
password_too_short=密碼長度不能少於 6 位! password_too_short=密碼長度不能少於 6 位!
[mail] [mail]
activate_account=Please activate your account activate_account=請激活您的帳戶
activate_email=Verify your email address activate_email=請驗證您的郵箱地址
reset_password=Reset your password reset_password=重置密碼
register_success=Registration successful, welcome register_success=註冊成功,歡迎使用
register_notify=Welcome on board register_notify=歡迎使用
[modal] [modal]
yes=確認操作 yes=確認操作
@ -192,7 +193,7 @@ min_size_error=長度最小為 %s 個字符。
max_size_error=長度最大為 %s 個字符。 max_size_error=長度最大為 %s 個字符。
email_error=不是一個有效的郵箱地址。 email_error=不是一個有效的郵箱地址。
url_error=不是一個有效的 URL。 url_error=不是一個有效的 URL。
include_error=` must contain substring '%s'.` include_error=必須包含子字符串 '%s'。
unknown_error=未知錯誤: unknown_error=未知錯誤:
captcha_incorrect=驗證碼未匹配。 captcha_incorrect=驗證碼未匹配。
password_not_match=密碼與確認密碼未匹配。 password_not_match=密碼與確認密碼未匹配。
@ -247,13 +248,14 @@ uid=用戶 ID
public_profile=公開信息 public_profile=公開信息
profile_desc=您的郵箱地址將會被公開,並被用於接收帳戶的所有提醒和通知。 profile_desc=您的郵箱地址將會被公開,並被用於接收帳戶的所有提醒和通知。
password_username_disabled=Non-local type users are not allowed to change their username.
full_name=自定義名稱 full_name=自定義名稱
website=個人網站 website=個人網站
location=所在地區 location=所在地區
update_profile=更新信息 update_profile=更新信息
update_profile_success=您的個人信息更新成功! update_profile_success=您的個人信息更新成功!
change_username=用戶名將被修改 change_username=用戶名將被修改
change_username_prompt=This change will affect the way how links relate to your account. change_username_prompt=該操作將會影響到所有與您帳戶有關的鏈接
continue=繼續操作 continue=繼續操作
cancel=取消操作 cancel=取消操作
@ -268,9 +270,10 @@ update_avatar_success=您的頭像設置更新成功!
change_password=修改密碼 change_password=修改密碼
old_password=當前密碼 old_password=當前密碼
new_password=新的密碼 new_password=新的密碼
retype_new_password=Retype New Password retype_new_password=重新輸入新的密碼
password_incorrect=當前密碼不正確! password_incorrect=當前密碼不正確!
change_password_success=密碼修改成功!您現在可以使用新的密碼登錄。 change_password_success=密碼修改成功!您現在可以使用新的密碼登錄。
password_change_disabled=Non-local type users are not allowed to change their password.
emails=電子郵件地址 emails=電子郵件地址
manage_emails=管理電子郵件地址 manage_emails=管理電子郵件地址
@ -278,9 +281,9 @@ email_desc=您的主要邮箱地址将被用于通知提醒和其它操作。
primary=主要 primary=主要
primary_email=设为主要 primary_email=设为主要
delete_email=刪除 delete_email=刪除
email_deletion=Email Deletion email_deletion=刪除郵箱
email_deletion_desc=Deleting this email address will remove related information from your account. Do you want to continue? email_deletion_desc=刪除該郵箱地址將會移除所有相關的信息。是否繼續?
email_deletion_success=Email has been deleted successfully! email_deletion_success=成功刪除郵箱!
add_new_email=添加新的電子郵件地址 add_new_email=添加新的電子郵件地址
add_email=添加電子郵件 add_email=添加電子郵件
add_email_confirmation_sent=一封待確認的電子郵件已發送到 '%s',請在%d 小時內檢查您的收件箱,並完成確認過程。 add_email_confirmation_sent=一封待確認的電子郵件已發送到 '%s',請在%d 小時內檢查您的收件箱,並完成確認過程。
@ -335,7 +338,7 @@ repo_name=倉庫名稱
repo_name_helper=偉大的倉庫名稱一般都較短、令人深刻並且 <strong>獨一無二</strong> 的。 repo_name_helper=偉大的倉庫名稱一般都較短、令人深刻並且 <strong>獨一無二</strong> 的。
visibility=可見度 visibility=可見度
visiblity_helper=該倉庫為 <span class="ui red text">私有的</span> visiblity_helper=該倉庫為 <span class="ui red text">私有的</span>
visiblity_helper_forced=Site admin has forced all new repositories to be <span class="ui red text">Private</span> visiblity_helper_forced=網站管理員已強制要求所有新建倉庫必須為 <span class="ui red text">私有的</span>
visiblity_fork_helper=(修改該值將會影響到所有派生倉庫) visiblity_fork_helper=(修改該值將會影響到所有派生倉庫)
clone_helper=不知道如何操作?訪問 <a target="_blank"href="%s"> 帮助説明</a> ! clone_helper=不知道如何操作?訪問 <a target="_blank"href="%s"> 帮助説明</a> !
fork_repo=派生倉庫 fork_repo=派生倉庫
@ -343,19 +346,22 @@ fork_from=派生自
fork_visiblity_helper=派生倉庫無法修改可見性。 fork_visiblity_helper=派生倉庫無法修改可見性。
repo_desc=倉庫描述 repo_desc=倉庫描述
repo_lang=倉庫語言 repo_lang=倉庫語言
repo_lang_helper=Select .gitignore files repo_lang_helper=請選擇 .gitignore 文件
license=授權許可 license=授權許可
license_helper=請選擇授權許可文件 license_helper=請選擇授權許可文件
readme=Readme readme=Readme
readme_helper=Select a readme template readme_helper=請選擇readme模板
auto_init=Initialize this repository with selected files and template auto_init=使用選定的文件和模板初始化倉庫
create_repo=創建倉庫 create_repo=創建倉庫
default_branch=默認分支 default_branch=默認分支
mirror_interval=鏡像同步周期(小時) mirror_interval=鏡像同步周期(小時)
watchers=Watchers mirror_address=Mirror Address
stargazers=Stargazers mirror_address_desc=Please include necessary user credentials in the address.
forks=Forks watchers=關注者
stargazers=稱讚者
forks=派生倉庫
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
form.name_reserved=倉庫名稱 '%s' 是被保留的。 form.name_reserved=倉庫名稱 '%s' 是被保留的。
form.name_pattern_not_allowed=倉庫名稱不允許 '%s' 的格式。 form.name_pattern_not_allowed=倉庫名稱不允許 '%s' 的格式。
@ -365,15 +371,16 @@ migrate_type_helper=該倉庫將是一個 <span class="text blue">鏡像</span>
migrate_repo=遷移倉庫 migrate_repo=遷移倉庫
migrate.clone_address=複製地址 migrate.clone_address=複製地址
migrate.clone_address_desc=該地址可以是 HTTP/HTTPS/GIT URL 或本地服務器路徑。 migrate.clone_address_desc=該地址可以是 HTTP/HTTPS/GIT URL 或本地服務器路徑。
migrate.permission_denied=You are not allowed to import local repositories. migrate.permission_denied=您並沒有導入本地倉庫的權限。
migrate.invalid_local_path=無效的本地路徑,該路徑不存在或不是一個目錄! migrate.invalid_local_path=無效的本地路徑,該路徑不存在或不是一個目錄!
migrate.failed=Migration failed: %v migrate.failed=遷移失敗:%v
mirror_from=mirror from
forked_from=派生自 forked_from=派生自
fork_from_self=無法派生已經擁有的倉庫! fork_from_self=無法派生已經擁有的倉庫!
copy_link=複製連結 copy_link=複製連結
copy_link_success=Copied! copy_link_success=複製成功!
copy_link_error=Press ⌘-C or Ctrl-C to copy copy_link_error=請按下 ⌘-C 或 Ctrl-C 複製
copied=複製成功 copied=複製成功
unwatch=取消關註 unwatch=取消關註
watch=關註 watch=關註
@ -386,16 +393,16 @@ quick_guide=快速幫助
clone_this_repo=複製當前倉庫 clone_this_repo=複製當前倉庫
create_new_repo_command=從命令行創建一個新的倉庫 create_new_repo_command=從命令行創建一個新的倉庫
push_exist_repo=從命令行推送已經創建的倉庫 push_exist_repo=從命令行推送已經創建的倉庫
repo_is_empty=This repository is empty, please come back later! repo_is_empty=這倉庫不包含任何內容,請稍後再訪問!
code=Code code=代碼
branch=分支 branch=分支
tree=目錄樹 tree=目錄樹
filter_branch_and_tag=Filter branch or tag filter_branch_and_tag=過濾分支或標籤
branches=分支列表 branches=分支列表
tags=標籤列表 tags=標籤列表
issues=問題管理 issues=問題管理
pulls=Pull Requests pulls=合併請求
labels=標籤 labels=標籤
milestones=里程碑 milestones=里程碑
commits=提交歷史 commits=提交歷史
@ -450,7 +457,7 @@ issues.filter_sort.recentupdate=最近更新
issues.filter_sort.leastupdate=最少更新 issues.filter_sort.leastupdate=最少更新
issues.filter_sort.mostcomment=最多評論 issues.filter_sort.mostcomment=最多評論
issues.filter_sort.leastcomment=最少評論 issues.filter_sort.leastcomment=最少評論
issues.opened_by=opened %[1]s by <a href="%[2]s">%[3]s</a> issues.opened_by=由 <a href="%[2]s">%[3]s</a> 與 %[1]s創建
issues.opened_by_fake=由 %[2]s 於 %[1]s創建 issues.opened_by_fake=由 %[2]s 於 %[1]s創建
issues.previous=上一頁 issues.previous=上一頁
issues.next=下一頁 issues.next=下一頁
@ -466,7 +473,7 @@ issues.reopen_comment_issue=重新開啟及評論
issues.create_comment=評論 issues.create_comment=評論
issues.closed_at=`於 <a id="%[1]s" href="#%[1]s">%[2]s</a> 關閉` issues.closed_at=`於 <a id="%[1]s" href="#%[1]s">%[2]s</a> 關閉`
issues.reopened_at=`於 <a id="%[1]s" href="#%[1]s">%[2]s</a> 重新開啟` issues.reopened_at=`於 <a id="%[1]s" href="#%[1]s">%[2]s</a> 重新開啟`
issues.commit_ref_at=`referenced this issue from a commit <a id="%[1]s" href="#%[1]s">%[2]s</a>` issues.commit_ref_at=`在代碼提交 <a id="%[1]s" href="#%[1]s">%[2]s</a> 中引用了該問題`
issues.poster=發佈者 issues.poster=發佈者
issues.admin=管理員 issues.admin=管理員
issues.owner=所有者 issues.owner=所有者
@ -486,31 +493,31 @@ issues.label_deletion=刪除標籤
issues.label_deletion_desc=刪除該標籤將會移除所有問題中相關的訊息。是否繼續? issues.label_deletion_desc=刪除該標籤將會移除所有問題中相關的訊息。是否繼續?
issues.label_deletion_success=標籤刪除成功! issues.label_deletion_success=標籤刪除成功!
pulls.new=New Pull Request pulls.new=創建合併請求
pulls.compare_changes=對比文件變化 pulls.compare_changes=對比文件變化
pulls.compare_changes_desc=對比兩個分支間的文件變化及發起一個合併請求。 pulls.compare_changes_desc=對比兩個分支間的文件變化及發起一個合併請求。
pulls.compare_base=base pulls.compare_base=基準分支
pulls.compare_compare=compare pulls.compare_compare=對比文件變化
pulls.filter_branch=Filter branch pulls.filter_branch=過濾分支
pulls.no_results=未找到結果 pulls.no_results=未找到結果
pulls.nothing_to_compare=There is nothing to compare because base and head branches are even. pulls.nothing_to_compare=基準和對比分支代碼已經同步,無需進行對比。
pulls.has_pull_request=`There is already a pull request between these two targets: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>` pulls.has_pull_request=`已經存在目標分支的合併請求:<a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
pulls.create=Create Pull Request pulls.create=創建合併請求
pulls.title_desc=wants to merge %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code> pulls.title_desc=請求將 %[1]d 次代碼提交從 <code>%[2]s</code> 合併至 <code>%[3]s</code>
pulls.merged_title_desc=merged %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code> %[4]s pulls.merged_title_desc=於 %[4]s 將 %[1]d 次代碼提交從 <code>%[2]s</code>合併至 <code>%[3]s</code>
pulls.tab_conversation=Conversation pulls.tab_conversation=對話內容
pulls.tab_commits=Commits pulls.tab_commits=代碼提交
pulls.tab_files=Files changed pulls.tab_files=文件變動
pulls.reopen_to_merge=Please reopen this pull request to perform merge operation. pulls.reopen_to_merge=請重新開啟合併請求來完成合併操作。
pulls.merged=Merged pulls.merged=已合併
pulls.has_merged=This pull request has been merged successfully! pulls.has_merged=該合併請求已經成功合併!
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information. pulls.data_broken=該合併請求的數據由於派生倉庫的相關信息被刪除而被破壞。
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments. pulls.is_checking=該合併請求正在進行衝突檢查,請稍後再刷新頁面。
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request. pulls.can_auto_merge_desc=This pull request can be merged automatically.
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits. pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
pulls.cannot_auto_merge_helper=Please use command line tool to solve it. pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
pulls.merge_pull_request=Merge Pull Request pulls.merge_pull_request=合併請求
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.` pulls.open_unmerged_pull_exists=`由於已經存在來自相同倉庫和合併信息的未合併請求(#%d),您無法執行重新開啟操作。`
milestones.new=新的里程碑 milestones.new=新的里程碑
milestones.open_tab=%d 開啟中 milestones.open_tab=%d 開啟中
@ -537,20 +544,20 @@ milestones.deletion_desc=刪除該里程碑將會移除所有問題中相關信
milestones.deletion_success=里程碑刪除成功! milestones.deletion_success=里程碑刪除成功!
wiki=Wiki wiki=Wiki
wiki.welcome=Welcome to Wiki! wiki.welcome=歡迎使用 Wiki!
wiki.welcome_desc=Wiki is the place where you would like to document your project together and make it better. wiki.welcome_desc=Wiki 是用於共同協作文檔的地方,清晰的文檔可以幫助其他人深入了解您的項目。
wiki.create_first_page=Create the first page wiki.create_first_page=創建第一個頁面
wiki.page=Page wiki.page=頁面
wiki.filter_page=Filter page wiki.filter_page=過濾頁面
wiki.new_page=Create New Page wiki.new_page=創建新的頁面
wiki.default_commit_message=Write a note about this update (optional). wiki.default_commit_message=關於此次修改的說明(可選)。
wiki.save_page=Save Page wiki.save_page=保存頁面
wiki.last_commit_info=%s edited this page %s wiki.last_commit_info=%s 於 %s 修改了此頁面
wiki.edit_page_button=Edit wiki.edit_page_button=修改
wiki.new_page_button=New Page wiki.new_page_button=新的頁面
wiki.page_already_exists=Wiki page with same name already exists. wiki.page_already_exists=相同名稱的 Wiki 頁面已經存在。
wiki.pages=Pages wiki.pages=所有頁面
wiki.last_updated=Last updated %s wiki.last_updated=最後更新於 %s
settings=倉庫設置 settings=倉庫設置
settings.options=基本設置 settings.options=基本設置
@ -560,29 +567,32 @@ settings.githooks=管理 Git 鉤子
settings.basic_settings=基本設置 settings.basic_settings=基本設置
settings.site=官方網站 settings.site=官方網站
settings.update_settings=更新倉庫設置 settings.update_settings=更新倉庫設置
settings.change_reponame_prompt=This change will affect how links relate to the repository. settings.change_reponame_prompt=該操作將會影響到所有與該倉庫有關的鏈接
settings.advanced_settings=Advanced Settings settings.advanced_settings=高級設置
settings.wiki_desc=Enable wiki to allow people write documents settings.wiki_desc=啟用 Wiki 以允許用戶協作文檔
settings.issues_desc=Enable builtin lightweight issue tracker settings.use_external_wiki=Use external wiki
settings.use_external_issue_tracker=Use external issue tracker settings.external_wiki_url=External Wiki URL
settings.tracker_url_format=External Issue Tracker URL Format settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index. settings.issues_desc=啟用內置的輕量級問題管理系統
settings.pulls_desc=Enable pull requests to accept public contributions settings.use_external_issue_tracker=使用外部的問題管理系統
settings.tracker_url_format=外部問題管理系統的 URL 格式
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分別作為用戶名、倉庫名和問題索引的占位符。
settings.pulls_desc=啟用合併請求以接受社區貢獻
settings.danger_zone=危險操作區 settings.danger_zone=危險操作區
settings.transfer=轉移倉庫所有權 settings.transfer=轉移倉庫所有權
settings.transfer_desc=您可以將倉庫轉移至您擁有管理員權限的帳戶或組織。 settings.transfer_desc=您可以將倉庫轉移至您擁有管理員權限的帳戶或組織。
settings.new_owner_has_same_repo=新的倉庫擁有者已經存在同名倉庫! settings.new_owner_has_same_repo=新的倉庫擁有者已經存在同名倉庫!
settings.delete=刪除本倉庫 settings.delete=刪除本倉庫
settings.delete_desc=刪除倉庫操作不可逆轉,請三思而後行。 settings.delete_desc=刪除倉庫操作不可逆轉,請三思而後行。
settings.transfer_notices_1=- You will lose access if new owner is a individual user. settings.transfer_notices_1=- 如果您將倉庫轉移給個人用戶,您將會丟失操作權限。
settings.transfer_notices_2=- You will conserve access if new owner is an organization and if you're one of the owners. settings.transfer_notices_2=- 如果您將倉庫轉移給您是所有者的組織,您的操作權限將被保留。
settings.transfer_form_title=Please enter following information to confirm your operation: settings.transfer_form_title=請輸入以下信息以確認您的操作:
settings.delete_notices_1=- This operation <strong>CANNOT</strong> be undone. settings.delete_notices_1=- 此操作 <strong>不可以</strong> 被回滾。
settings.delete_notices_2=- This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators. settings.delete_notices_2=- 此操作將永久刪除該倉庫,包括 Git 數據、 問題、 評論和協作者的操作權限。
settings.delete_notices_fork_1=- If this repository is public, all forks will be became independent after deletion. settings.delete_notices_fork_1=- 如果該倉庫為公開的,則在刪除倉庫後所有的派生倉庫都將轉換成獨立的倉庫。
settings.delete_notices_fork_2=- If this repository is private, all forks will be removed at the same time. settings.delete_notices_fork_2=- 如果該倉庫為私有,則會同時刪除所有的派生倉庫。
settings.delete_notices_fork_3=- If you want to keep all forks after deletion, please change visibility of this repository to public first. settings.delete_notices_fork_3=- 如果您想要保留派生倉庫,請先將可見性修改為公開的後再進行刪除操作。
settings.deletion_success=Repository has been deleted successfully! settings.deletion_success=倉庫刪除成功!
settings.update_settings_success=倉庫設置更新成功! settings.update_settings_success=倉庫設置更新成功!
settings.transfer_owner=新擁有者 settings.transfer_owner=新擁有者
settings.make_transfer=確認轉移倉庫 settings.make_transfer=確認轉移倉庫
@ -591,21 +601,21 @@ settings.confirm_delete=確認刪除倉庫
settings.add_collaborator=增加新的協作者 settings.add_collaborator=增加新的協作者
settings.add_collaborator_success=成功添加新的協作者! settings.add_collaborator_success=成功添加新的協作者!
settings.remove_collaborator_success=被操作的協作者已經被收回權限! settings.remove_collaborator_success=被操作的協作者已經被收回權限!
settings.search_user_placeholder=Search user... settings.search_user_placeholder=搜索用戶...
settings.user_is_org_member=被操作的用戶是組織成員,因此無法添加為協作者! settings.user_is_org_member=被操作的用戶是組織成員,因此無法添加為協作者!
settings.add_webhook=添加 Web 鉤子 settings.add_webhook=添加 Web 鉤子
settings.hooks_desc=Web 鉤子允許您設定在 Gogs 上發生指定事件時對指定 URL 發送 POST 通知。查看 <a target="_blank" href="%s">Webhooks 文檔</a> 獲取更多信息。 settings.hooks_desc=Web 鉤子允許您設定在 Gogs 上發生指定事件時對指定 URL 發送 POST 通知。查看 <a target="_blank" href="%s">Webhooks 文檔</a> 獲取更多信息。
settings.webhook_deletion=Delete Webhook settings.webhook_deletion=刪除 Web 鉤子
settings.webhook_deletion_desc=Delete this webhook will remove its information and all delivery history. Do you want to continue? settings.webhook_deletion_desc=刪除該 Web 鉤子將會刪除與其有關的信息和推送歷史。是否繼續?
settings.webhook_deletion_success=Webhook has been deleted successfully! settings.webhook_deletion_success=Web 鉤子刪除成功!
settings.webhook.test_delivery=Test Delivery settings.webhook.test_delivery=測試推送
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings settings.webhook.test_delivery_desc=生成並推送一個模擬的 Push 事件
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history. settings.webhook.test_delivery_success=測試推送已經加入到隊列,請耐心等待數秒再刷新推送記錄。
settings.webhook.request=Request settings.webhook.request=請求內容
settings.webhook.response=Response settings.webhook.response=響應內容
settings.webhook.headers=Headers settings.webhook.headers=標題
settings.webhook.payload=Payload settings.webhook.payload=推送內容
settings.webhook.body=Body settings.webhook.body=響應內容
settings.githooks_desc=Git 鉤子是由 Git 本身提供的功能,以下為 Gogs 所支持的鉤子列表。 settings.githooks_desc=Git 鉤子是由 Git 本身提供的功能,以下為 Gogs 所支持的鉤子列表。
settings.githook_edit_desc=如果鉤子未啟動,則會顯示樣例文件中的內容。如果想要刪除某個鉤子,則提交空白文本即可。 settings.githook_edit_desc=如果鉤子未啟動,則會顯示樣例文件中的內容。如果想要刪除某個鉤子,則提交空白文本即可。
settings.githook_name=鉤子名稱 settings.githook_name=鉤子名稱
@ -615,17 +625,17 @@ settings.add_webhook_desc=我們會通過 <code>POST</code> 請求將訂閱事
settings.payload_url=推送地址 settings.payload_url=推送地址
settings.content_type=數據格式 settings.content_type=數據格式
settings.secret=密鑰文本 settings.secret=密鑰文本
settings.slack_username=Username settings.slack_username=服務名稱
settings.slack_icon_url=Icon URL settings.slack_icon_url=圖標 URL
settings.slack_color=Color settings.slack_color=顏色代碼
settings.event_desc=請設置您希望觸發 Web 鉤子的事件: settings.event_desc=請設置您希望觸發 Web 鉤子的事件:
settings.event_push_only=只推送 <code>push</code> 事件。 settings.event_push_only=只推送 <code>push</code> 事件。
settings.event_send_everything=I need <strong>everything</strong>. settings.event_send_everything=推送 <strong>所有</strong> 事件
settings.event_choose=Let me choose what I need. settings.event_choose=讓我選擇我的需要
settings.event_create=Create settings.event_create=創建
settings.event_create_desc=Branch, or tag created settings.event_create_desc=創建分支或標籤
settings.event_push=Push settings.event_push=推送
settings.event_push_desc=Git push to a repository settings.event_push_desc=Git 倉庫推送
settings.active=是否激活 settings.active=是否激活
settings.active_helper=當指定事件發生時我們將會觸發此 Web 鉤子。 settings.active_helper=當指定事件發生時我們將會觸發此 Web 鉤子。
settings.add_hook_success=Web 鉤子添加成功! settings.add_hook_success=Web 鉤子添加成功!
@ -640,7 +650,7 @@ settings.slack_domain=域名
settings.slack_channel=頻道 settings.slack_channel=頻道
settings.deploy_keys=管理部署密鑰 settings.deploy_keys=管理部署密鑰
settings.add_deploy_key=添加部署密鑰 settings.add_deploy_key=添加部署密鑰
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys. settings.deploy_key_desc=部署密鑰僅具有隻讀權限,它在功能上和個人用戶的公開密鑰有本質區別。
settings.no_deploy_keys=您還沒有添加任何部署密鑰。 settings.no_deploy_keys=您還沒有添加任何部署密鑰。
settings.title=標題 settings.title=標題
settings.deploy_key_content=密鑰文本 settings.deploy_key_content=密鑰文本
@ -668,32 +678,32 @@ release.stable=穩定
release.edit=編輯 release.edit=編輯
release.ahead=在該版本發佈之後已有 <strong>%d</strong> 次代碼提交到 %s 分支 release.ahead=在該版本發佈之後已有 <strong>%d</strong> 次代碼提交到 %s 分支
release.source_code=源代碼 release.source_code=源代碼
release.new_subheader=Publish releases to iterate product. release.new_subheader=發布版本對產品進行迭代。
release.edit_subheader=Detailed change log can help users understand what has been improved. release.edit_subheader=詳細的變更日誌可以幫助用戶更好地了解產品做了哪些改進。
release.tag_name=標籤名稱 release.tag_name=標籤名稱
release.target=目標分支 release.target=目標分支
release.tag_helper=選擇或創建一個已存在的標籤 release.tag_helper=選擇或創建一個已存在的標籤
release.title=Title release.title=標題
release.content=Content release.content=內容
release.write=內容編輯 release.write=內容編輯
release.preview=效果預覽 release.preview=效果預覽
release.loading=正在加載... release.loading=正在加載...
release.prerelease_desc=這是一個預發佈版本 release.prerelease_desc=這是一個預發佈版本
release.prerelease_helper=我們會告知用戶不建議將本發佈投入生產環境使用。 release.prerelease_helper=我們會告知用戶不建議將本發佈投入生產環境使用。
release.cancel=Cancel release.cancel=取消
release.publish=發佈版本 release.publish=發佈版本
release.save_draft=保在草稿 release.save_draft=保在草稿
release.edit_release=編輯發佈信息 release.edit_release=編輯發佈信息
release.delete_release=Delete This Release release.delete_release=刪除此次發布
release.deletion=Release Deletion release.deletion=刪除版本發布操作
release.deletion_desc=Deleting this release will delete the corresponding Git tag. Do you want to continue? release.deletion_desc=刪除該版本發布將會移除相應的 Git 標籤。是否繼續?
release.deletion_success=Release has been deleted successfully! release.deletion_success=版本發布刪除成功!
release.tag_name_already_exist=已經存在使用相同標籤的發佈版本。 release.tag_name_already_exist=已經存在使用相同標籤的發佈版本。
release.downloads=Downloads release.downloads=下載附件
[org] [org]
org_name_holder=組織名稱 org_name_holder=組織名稱
org_full_name_holder=Organization Full Name org_full_name_holder=組織全名
org_name_helper=偉大的組織都有一個簡短而寓意深刻的名字。 org_name_helper=偉大的組織都有一個簡短而寓意深刻的名字。
create_org=創建組織 create_org=創建組織
repo_updated=最後更新於 repo_updated=最後更新於
@ -720,8 +730,8 @@ settings.website=官方網站
settings.location=所在地區 settings.location=所在地區
settings.update_settings=更新組織設置 settings.update_settings=更新組織設置
settings.update_setting_success=組織設置更新成功! settings.update_setting_success=組織設置更新成功!
settings.change_orgname_prompt=This change will affect how links relate to the organization. settings.change_orgname_prompt=該操作將會影響到所有與該組織有關的鏈接
settings.update_avatar_success=Organization avatar setting has been updated successfully. settings.update_avatar_success=組織頭像更新成功!
settings.delete=刪除組織 settings.delete=刪除組織
settings.delete_account=刪除當前組織 settings.delete_account=刪除當前組織
settings.delete_prompt=刪除操作會永久清除該組織的信息,並且 <strong>不可恢復</strong>! settings.delete_prompt=刪除操作會永久清除該組織的信息,並且 <strong>不可恢復</strong>!
@ -730,17 +740,17 @@ settings.delete_org_title=組織刪除操作
settings.delete_org_desc=該組織將被永久性刪除,您確定要繼續操作嗎? settings.delete_org_desc=該組織將被永久性刪除,您確定要繼續操作嗎?
settings.hooks_desc=在此處添加的 Web 鉤子將會應用到該組織下的 <strong>所有倉庫</strong>。 settings.hooks_desc=在此處添加的 Web 鉤子將會應用到該組織下的 <strong>所有倉庫</strong>。
members.membership_visibility=Membership Visibility: members.membership_visibility=成員可見性:
members.public=公開成員 members.public=公開成員
members.public_helper=設為私有 members.public_helper=設為私有
members.private=私有成員 members.private=私有成員
members.private_helper=設為公開 members.private_helper=設為公開
members.member_role=Member Role: members.member_role=成員角色:
members.owner=管理員 members.owner=管理員
members.member=普通成員 members.member=普通成員
members.remove=移除成員 members.remove=移除成員
members.leave=離開組織 members.leave=離開組織
members.invite_desc=Add a new member to %s: members.invite_desc=邀請新的用戶加入 %s:
members.invite_now=立即邀請 members.invite_now=立即邀請
teams.join=加入團隊 teams.join=加入團隊
@ -765,7 +775,7 @@ teams.read_permission_desc=該團隊擁有對所屬倉庫的 <strong>讀取</str
teams.write_permission_desc=該團隊擁有對所屬倉庫的 <strong>讀取</strong> 和 <strong>寫入</strong> 的權限。 teams.write_permission_desc=該團隊擁有對所屬倉庫的 <strong>讀取</strong> 和 <strong>寫入</strong> 的權限。
teams.admin_permission_desc=該團隊擁有一定的 <strong>管理</strong> 權限,團隊成員可以讀取、複製、推送以及添加其它倉庫協作者。 teams.admin_permission_desc=該團隊擁有一定的 <strong>管理</strong> 權限,團隊成員可以讀取、複製、推送以及添加其它倉庫協作者。
teams.repositories=團隊倉庫 teams.repositories=團隊倉庫
teams.search_repo_placeholder=Search repository... teams.search_repo_placeholder=搜索倉庫...
teams.add_team_repository=添加團隊倉庫 teams.add_team_repository=添加團隊倉庫
teams.remove_repo=移除倉庫 teams.remove_repo=移除倉庫
teams.add_nonexistent_repo=您嘗試添加到團隊的倉庫不存在,請先創建倉庫! teams.add_nonexistent_repo=您嘗試添加到團隊的倉庫不存在,請先創建倉庫!
@ -779,9 +789,9 @@ authentication=授權認證管理
config=應用配置管理 config=應用配置管理
notices=系統提示管理 notices=系統提示管理
monitor=應用監控面版 monitor=應用監控面版
first_page=First first_page=首頁
last_page=Last last_page=末頁
total=Total: %d total=總計:%d
dashboard.statistic=應用統計數據 dashboard.statistic=應用統計數據
dashboard.operations=管理員操作 dashboard.operations=管理員操作
@ -796,8 +806,8 @@ dashboard.delete_inactivate_accounts=刪除所有未激活帳戶
dashboard.delete_inactivate_accounts_success=所有未激活帳號清除成功! dashboard.delete_inactivate_accounts_success=所有未激活帳號清除成功!
dashboard.delete_repo_archives=刪除所有倉庫存檔 dashboard.delete_repo_archives=刪除所有倉庫存檔
dashboard.delete_repo_archives_success=所有倉庫存檔清除成功! dashboard.delete_repo_archives_success=所有倉庫存檔清除成功!
dashboard.delete_missing_repos=Delete all repository records that lost Git files dashboard.delete_missing_repos=刪除所有丟失 Git 文件的倉庫記錄
dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully. dashboard.delete_missing_repos_success=成功刪除所有丟失 Git 文件的倉庫記錄!
dashboard.git_gc_repos=對倉庫進行垃圾回收 dashboard.git_gc_repos=對倉庫進行垃圾回收
dashboard.git_gc_repos_success=所有倉庫的垃圾回收已成功完成! dashboard.git_gc_repos_success=所有倉庫的垃圾回收已成功完成!
dashboard.resync_all_sshkeys=重新生成 '.ssh/authorized_keys' 文件(警告:不是 Gogs 的密鑰也會被刪除) dashboard.resync_all_sshkeys=重新生成 '.ssh/authorized_keys' 文件(警告:不是 Gogs 的密鑰也會被刪除)
@ -842,24 +852,26 @@ users.activated=已激活
users.admin=管理員 users.admin=管理員
users.repos=倉庫數 users.repos=倉庫數
users.created=創建時間 users.created=創建時間
users.send_register_notify=Send Registration Notification To User users.send_register_notify=向用戶發送註冊通知郵件
users.new_success=New account '%s' has been created successfully. users.new_success=新用戶 '%s' 創建成功!
users.edit=編輯 users.edit=編輯
users.auth_source=Authentication Source users.auth_source=認證源
users.local=本地 users.local=本地
users.auth_login_name=Authentication Login Name users.auth_login_name=認證登錄名稱
users.password_helper=Leave it empty to remain unchanged. users.password_helper=留空使其保持不變。
users.update_profile_success=該用戶信息更新成功! users.update_profile_success=該用戶信息更新成功!
users.edit_account=編輯用戶信息 users.edit_account=編輯用戶信息
users.max_repo_creation=Maximum Repository Creation Limit
users.max_repo_creation_desc=(Set -1 to use global default limit)
users.is_activated=該用戶已被激活 users.is_activated=該用戶已被激活
users.is_admin=該用戶具有管理員權限 users.is_admin=該用戶具有管理員權限
users.allow_git_hook=該帳戶具有創建 Git 鉤子的權限 users.allow_git_hook=該帳戶具有創建 Git 鉤子的權限
users.allow_import_local=This account has permissions to import local repositories users.allow_import_local=該用戶具有導入本地倉庫的權限
users.update_profile=更新用戶信息 users.update_profile=更新用戶信息
users.delete_account=刪除該用戶 users.delete_account=刪除該用戶
users.still_own_repo=該帳戶仍然是某些倉庫的擁有者,您必須先轉移或刪除它們才能執行刪除帳戶操作! users.still_own_repo=該帳戶仍然是某些倉庫的擁有者,您必須先轉移或刪除它們才能執行刪除帳戶操作!
users.still_has_org=該帳戶仍舊是某些組織的成員,您必須先使其離開或刪除組織。 users.still_has_org=該帳戶仍舊是某些組織的成員,您必須先使其離開或刪除組織。
users.deletion_success=Account has been deleted successfully! users.deletion_success=用戶刪除成功!
orgs.org_manage_panel=組織管理面版 orgs.org_manage_panel=組織管理面版
orgs.name=組織名稱 orgs.name=組織名稱
@ -874,49 +886,49 @@ repos.watches=關註數
repos.stars=讚好數 repos.stars=讚好數
repos.issues=問題數 repos.issues=問題數
auths.auth_manage_panel=Authentication Manage Panel auths.auth_manage_panel=認證管理面板
auths.new=Add New Source auths.new=添加新認證源
auths.name=認證名稱 auths.name=認證名稱
auths.type=認證類型 auths.type=認證類型
auths.enabled=已啟用 auths.enabled=已啟用
auths.updated=最後更新時間 auths.updated=最後更新時間
auths.auth_type=Authentication Type auths.auth_type=認證類型
auths.auth_name=Authentication Name auths.auth_name=認證名稱
auths.domain=域名 auths.domain=域名
auths.host=主機地址 auths.host=主機地址
auths.port=主機端口 auths.port=主機端口
auths.bind_dn=綁定DN auths.bind_dn=綁定DN
auths.bind_password=綁定密碼 auths.bind_password=綁定密碼
auths.bind_password_helper=Warning: This password is stored in plain text. Do not use a high privileged account. auths.bind_password_helper=警告:該密碼將會以明文的形式保存在數據庫中。請不要使用擁有高權限的帳戶!
auths.user_base=User Search Base auths.user_base=用戶搜索基準
auths.user_dn=User DN auths.user_dn=User DN
auths.attribute_username=Username attribute auths.attribute_username=用戶名屬性
auths.attribute_username_placeholder=Leave empty to use sign-in form field value for user name. auths.attribute_username_placeholder=留空表示使用用戶登錄時所使用的用戶名
auths.attribute_name=名子屬性 auths.attribute_name=名子屬性
auths.attribute_surname=姓氏屬性 auths.attribute_surname=姓氏屬性
auths.attribute_mail=電子郵箱屬性 auths.attribute_mail=電子郵箱屬性
auths.filter=使用者篩選器 auths.filter=使用者篩選器
auths.admin_filter=管理者篩選器 auths.admin_filter=管理者篩選器
auths.ms_ad_sa=Ms Ad SA auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=SMTP Authentication Type auths.smtp_auth=SMTP 驗證類型
auths.smtphost=SMTP 主機地址 auths.smtphost=SMTP 主機地址
auths.smtpport=SMTP 主機端口 auths.smtpport=SMTP 主機端口
auths.allowed_domains=Allowed Domains auths.allowed_domains=域名白名單
auths.allowed_domains_helper=Leave it empty to not restrict any domains. Multiple domains should be separated by comma ','. auths.allowed_domains_helper=留空表示不對域名做任何限制。多個域名之間需要使用逗號 ',' 分隔。
auths.enable_tls=啟用 TLS 加密 auths.enable_tls=啟用 TLS 加密
auths.skip_tls_verify=Skip TLS Verify auths.skip_tls_verify=忽略 TLS 驗證
auths.pam_service_name=PAM 服務名稱 auths.pam_service_name=PAM 服務名稱
auths.enable_auto_register=允許授權用戶自動註冊 auths.enable_auto_register=允許授權用戶自動註冊
auths.tips=幫助提示 auths.tips=幫助提示
auths.edit=Edit Authentication Setting auths.edit=編輯認證設置
auths.activated=該授權認證已經啟用 auths.activated=該授權認證已經啟用
auths.new_success=New authentication '%s' has been added successfully. auths.new_success=新的認證源 "%s" 添加成功!
auths.update_success=Authentication setting has been updated successfully. auths.update_success=認證設置更新成功!
auths.update=Update Authentication Setting auths.update=更新認證設置
auths.delete=Delete This Authentication auths.delete=刪除該認證
auths.delete_auth_title=Authentication Deletion auths.delete_auth_title=刪除認證操作
auths.delete_auth_desc=This authentication is going to be deleted, do you want to continue? auths.delete_auth_desc=該認證將被刪除。是否繼續?
auths.deletion_success=Authentication has been deleted successfully! auths.deletion_success=認證源刪除成功!
config.server_config=服務器配置 config.server_config=服務器配置
config.app_name=應用名稱 config.app_name=應用名稱
@ -940,7 +952,7 @@ config.db_user=數據庫用戶
config.db_ssl_mode=SSL 模式 config.db_ssl_mode=SSL 模式
config.db_ssl_mode_helper=(僅限 "postgres" 使用) config.db_ssl_mode_helper=(僅限 "postgres" 使用)
config.db_path=數據庫路徑 config.db_path=數據庫路徑
config.db_path_helper=(for "sqlite3" and "tidb") config.db_path_helper=(用於 "sqlite3" 和 "tidb")
config.service_config=服務配置 config.service_config=服務配置
config.register_email_confirm=註冊電子郵件確認 config.register_email_confirm=註冊電子郵件確認
config.disable_register=關閉註冊功能 config.disable_register=關閉註冊功能
@ -948,8 +960,8 @@ config.show_registration_button=顯示註冊按鈕
config.require_sign_in_view=強制登錄瀏覽 config.require_sign_in_view=強制登錄瀏覽
config.enable_cache_avatar=開啟緩存頭像 config.enable_cache_avatar=開啟緩存頭像
config.mail_notify=郵件通知提醒 config.mail_notify=郵件通知提醒
config.disable_key_size_check=Disable Minimum Key Size Check config.disable_key_size_check=禁用密鑰最小長度檢查
config.enable_captcha=Enable Captcha config.enable_captcha=啟用驗證碼服務
config.active_code_lives=激活用戶連結有效期 config.active_code_lives=激活用戶連結有效期
config.reset_password_code_lives=重置密碼連結有效期 config.reset_password_code_lives=重置密碼連結有效期
config.webhook_config=Web 鉤子配置 config.webhook_config=Web 鉤子配置
@ -995,30 +1007,30 @@ monitor.start=開始時間
monitor.execute_time=已執行時間 monitor.execute_time=已執行時間
notices.system_notice_list=系統提示管理 notices.system_notice_list=系統提示管理
notices.view_detail_header=View Notice Detail notices.view_detail_header=查看提示詳情
notices.actions=Actions notices.actions=操作
notices.select_all=Select All notices.select_all=選取全部
notices.deselect_all=Deselect All notices.deselect_all=取消所有選取
notices.inverse_selection=Inverse Selection notices.inverse_selection=反向選取
notices.delete_selected=Delete Selected notices.delete_selected=刪除選取項
notices.delete_all=Delete All Notices notices.delete_all=刪除所有提示
notices.type=提示類型 notices.type=提示類型
notices.type_1=倉庫 notices.type_1=倉庫
notices.desc=描述 notices.desc=描述
notices.op=操作 notices.op=操作
notices.delete_success=System notices have been deleted successfully. notices.delete_success=系統提示刪除成功!
[action] [action]
create_repo=創建了倉庫 <a href="%s">%s</a> create_repo=創建了倉庫 <a href="%s">%s</a>
rename_repo=renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]s</a> rename_repo=重新命名倉庫 <code>%[1]s</code> 為 <a href="%[2]s">%[3]s</a>
commit_repo=推送了 <a href="%[1]s/src/%[2]s">%[3]s</a> 分支的代碼到 <a href="%[1]s">%[4]s</a> commit_repo=推送了 <a href="%[1]s/src/%[2]s">%[3]s</a> 分支的代碼到 <a href="%[1]s">%[4]s</a>
create_issue=`創建了問題 <a href="%s/issues/%s">%s#%[2]s</a>` create_issue=`創建了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
create_pull_request=`created pull request <a href="%s/pulls/%s">%s#%[2]s</a>` create_pull_request=`創建了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>` comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>` merge_pull_request=`合併了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
transfer_repo=將倉庫 <code>%s</code> 轉移至 <a href="%s">%s</a> transfer_repo=將倉庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
push_tag=推送了標籤 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a> push_tag=推送了標籤 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_commits=查看 %d 次提交的內容對比 compare_commits=View comparison for these %d commits
[tool] [tool]
ago=之前 ago=之前

2
docker/README.md

@ -1,6 +1,6 @@
# Docker for Gogs # Docker for Gogs
Visit [Docker Hub](https://hub.docker.com/r/gogs/gogs/) or [QUAY](https://quay.io/repository/gogs/gogs) see all available tags. Visit [Docker Hub](https://hub.docker.com/r/gogs/gogs/) or [Quay](https://quay.io/repository/gogs/gogs) see all available tags.
## Usage ## Usage

4
docker/build.sh

@ -13,8 +13,8 @@ apk -U --no-progress add linux-pam-dev go@community gcc musl-dev
mkdir -p ${GOPATH}/src/github.com/gogits/ mkdir -p ${GOPATH}/src/github.com/gogits/
ln -s /app/gogs/ ${GOPATH}/src/github.com/gogits/gogs ln -s /app/gogs/ ${GOPATH}/src/github.com/gogits/gogs
cd ${GOPATH}/src/github.com/gogits/gogs cd ${GOPATH}/src/github.com/gogits/gogs
go get -v -tags "sqlite redis memcache cert pam" go get -v -tags "sqlite cert pam"
go build -tags "sqlite redis memcache cert pam" go build -tags "sqlite cert pam"
# Cleanup GOPATH # Cleanup GOPATH
rm -r $GOPATH rm -r $GOPATH

5
gogs.go

@ -1,4 +1,4 @@
// +build go1.3 // +build go1.4
// Copyright 2014 The Gogs Authors. All rights reserved. // Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
@ -12,12 +12,13 @@ import (
"runtime" "runtime"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
_ "github.com/kardianos/minwinsvc"
"github.com/gogits/gogs/cmd" "github.com/gogits/gogs/cmd"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
const APP_VER = "0.7.35.1209 Beta" const APP_VER = "0.8.7.1215"
func init() { func init() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())

50
models/action.go

@ -17,10 +17,10 @@ import (
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client" api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
@ -229,6 +229,28 @@ func NewPushCommits() *PushCommits {
} }
} }
func (pc *PushCommits) ToApiPayloadCommits(repoLink string) []*api.PayloadCommit {
commits := make([]*api.PayloadCommit, len(pc.Commits))
for i, cmt := range pc.Commits {
author_username := ""
author, err := GetUserByEmail(cmt.AuthorEmail)
if err == nil {
author_username = author.Name
}
commits[i] = &api.PayloadCommit{
ID: cmt.Sha1,
Message: cmt.Message,
URL: fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1),
Author: &api.PayloadAuthor{
Name: cmt.AuthorName,
Email: cmt.AuthorEmail,
UserName: author_username,
},
}
}
return commits
}
// AvatarLink tries to match user in database with e-mail // AvatarLink tries to match user in database with e-mail
// in order to show custom avatar, and falls back to general avatar link. // in order to show custom avatar, and falls back to general avatar link.
func (push *PushCommits) AvatarLink(email string) string { func (push *PushCommits) AvatarLink(email string) string {
@ -413,15 +435,11 @@ func CommitRepoAction(
} else { } else {
// if not the first commit, set the compareUrl // if not the first commit, set the compareUrl
if !strings.HasPrefix(oldCommitID, "0000000") { if !strings.HasPrefix(oldCommitID, "0000000") {
commit.CompareUrl = fmt.Sprintf("%s/%s/compare/%s...%s", repoUserName, repoName, oldCommitID, newCommitID) commit.CompareUrl = repo.ComposeCompareURL(oldCommitID, newCommitID)
} else { } else {
isNewBranch = true isNewBranch = true
} }
// NOTE: limit to detect latest 100 commits.
if len(commit.Commits) > 100 {
commit.Commits = commit.Commits[len(commit.Commits)-100:]
}
if err = updateIssuesCommit(u, repo, repoUserName, repoName, commit.Commits); err != nil { if err = updateIssuesCommit(u, repo, repoUserName, repoName, commit.Commits); err != nil {
log.Error(4, "updateIssuesCommit: %v", err) log.Error(4, "updateIssuesCommit: %v", err)
} }
@ -469,30 +487,12 @@ func CommitRepoAction(
switch opType { switch opType {
case COMMIT_REPO: // Push case COMMIT_REPO: // Push
commits := make([]*api.PayloadCommit, len(commit.Commits))
for i, cmt := range commit.Commits {
author_username := ""
author, err := GetUserByEmail(cmt.AuthorEmail)
if err == nil {
author_username = author.Name
}
commits[i] = &api.PayloadCommit{
ID: cmt.Sha1,
Message: cmt.Message,
URL: fmt.Sprintf("%s/commit/%s", repo.FullRepoLink(), cmt.Sha1),
Author: &api.PayloadAuthor{
Name: cmt.AuthorName,
Email: cmt.AuthorEmail,
UserName: author_username,
},
}
}
p := &api.PushPayload{ p := &api.PushPayload{
Ref: refFullName, Ref: refFullName,
Before: oldCommitID, Before: oldCommitID,
After: newCommitID, After: newCommitID,
CompareUrl: setting.AppUrl + commit.CompareUrl, CompareUrl: setting.AppUrl + commit.CompareUrl,
Commits: commits, Commits: commit.ToApiPayloadCommits(repo.FullRepoLink()),
Repo: payloadRepo, Repo: payloadRepo,
Pusher: &api.PayloadAuthor{ Pusher: &api.PayloadAuthor{
Name: pusher_name, Name: pusher_name,

13
models/error.go

@ -107,6 +107,19 @@ func (err ErrUserHasOrgs) Error() string {
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID) return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
} }
type ErrReachLimitOfRepo struct {
Limit int
}
func IsErrReachLimitOfRepo(err error) bool {
_, ok := err.(ErrReachLimitOfRepo)
return ok
}
func (err ErrReachLimitOfRepo) Error() string {
return fmt.Sprintf("user has reached maximum limit of repositories [limit: %d]", err.Limit)
}
// __ __.__ __ .__ // __ __.__ __ .__
// / \ / \__| | _|__| // / \ / \__| | _|__|
// \ \/\/ / | |/ / | // \ \/\/ / | |/ / |

8
models/git_diff.go

@ -9,6 +9,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
@ -17,7 +18,7 @@ import (
"golang.org/x/net/html/charset" "golang.org/x/net/html/charset"
"golang.org/x/text/transform" "golang.org/x/text/transform"
"github.com/gogits/git-shell" "github.com/gogits/git-module"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
@ -124,6 +125,7 @@ func ParsePatch(maxlines int, reader io.Reader) (*Diff, error) {
// Diff data too large, we only show the first about maxlines lines // Diff data too large, we only show the first about maxlines lines
if lineCount >= maxlines { if lineCount >= maxlines {
log.Warn("Diff data too large") log.Warn("Diff data too large")
io.Copy(ioutil.Discard, reader)
diff.Files = nil diff.Files = nil
return diff, nil return diff, nil
} }
@ -244,8 +246,8 @@ func ParsePatch(maxlines int, reader io.Reader) (*Diff, error) {
buf.WriteString("\n") buf.WriteString("\n")
} }
} }
charsetLabel, err := base.DetectEncoding(buf.Bytes()) charsetLabel := base.DetectEncoding(buf.Bytes())
if charsetLabel != "UTF-8" && err == nil { if charsetLabel != "UTF-8" {
encoding, _ := charset.Lookup(charsetLabel) encoding, _ := charset.Lookup(charsetLabel)
if encoding != nil { if encoding != nil {
d := encoding.NewDecoder() d := encoding.NewDecoder()

71
models/login.go

@ -10,6 +10,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/smtp" "net/smtp"
"net/textproto"
"strings" "strings"
"time" "time"
@ -26,12 +27,12 @@ type LoginType int
// Note: new type must be added at the end of list to maintain compatibility. // Note: new type must be added at the end of list to maintain compatibility.
const ( const (
NOTYPE LoginType = iota LOGIN_NOTYPE LoginType = iota
PLAIN LOGIN_PLAIN
LDAP LOGIN_LDAP
SMTP LOGIN_SMTP
PAM LOGIN_PAM
DLDAP LOGIN_DLDAP
) )
var ( var (
@ -40,10 +41,10 @@ var (
) )
var LoginNames = map[LoginType]string{ var LoginNames = map[LoginType]string{
LDAP: "LDAP (via BindDN)", LOGIN_LDAP: "LDAP (via BindDN)",
DLDAP: "LDAP (simple auth)", LOGIN_DLDAP: "LDAP (simple auth)",
SMTP: "SMTP", LOGIN_SMTP: "SMTP",
PAM: "PAM", LOGIN_PAM: "PAM",
} }
// Ensure structs implemented interface. // Ensure structs implemented interface.
@ -108,11 +109,11 @@ func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) {
switch colName { switch colName {
case "type": case "type":
switch LoginType((*val).(int64)) { switch LoginType((*val).(int64)) {
case LDAP, DLDAP: case LOGIN_LDAP, LOGIN_DLDAP:
source.Cfg = new(LDAPConfig) source.Cfg = new(LDAPConfig)
case SMTP: case LOGIN_SMTP:
source.Cfg = new(SMTPConfig) source.Cfg = new(SMTPConfig)
case PAM: case LOGIN_PAM:
source.Cfg = new(PAMConfig) source.Cfg = new(PAMConfig)
default: default:
panic("unrecognized login source type: " + com.ToStr(*val)) panic("unrecognized login source type: " + com.ToStr(*val))
@ -125,26 +126,26 @@ func (source *LoginSource) TypeName() string {
} }
func (source *LoginSource) IsLDAP() bool { func (source *LoginSource) IsLDAP() bool {
return source.Type == LDAP return source.Type == LOGIN_LDAP
} }
func (source *LoginSource) IsDLDAP() bool { func (source *LoginSource) IsDLDAP() bool {
return source.Type == DLDAP return source.Type == LOGIN_DLDAP
} }
func (source *LoginSource) IsSMTP() bool { func (source *LoginSource) IsSMTP() bool {
return source.Type == SMTP return source.Type == LOGIN_SMTP
} }
func (source *LoginSource) IsPAM() bool { func (source *LoginSource) IsPAM() bool {
return source.Type == PAM return source.Type == LOGIN_PAM
} }
func (source *LoginSource) UseTLS() bool { func (source *LoginSource) UseTLS() bool {
switch source.Type { switch source.Type {
case LDAP, DLDAP: case LOGIN_LDAP, LOGIN_DLDAP:
return source.LDAP().UseSSL return source.LDAP().UseSSL
case SMTP: case LOGIN_SMTP:
return source.SMTP().TLS return source.SMTP().TLS
} }
@ -153,9 +154,9 @@ func (source *LoginSource) UseTLS() bool {
func (source *LoginSource) SkipVerify() bool { func (source *LoginSource) SkipVerify() bool {
switch source.Type { switch source.Type {
case LDAP, DLDAP: case LOGIN_LDAP, LOGIN_DLDAP:
return source.LDAP().SkipVerify return source.LDAP().SkipVerify
case SMTP: case LOGIN_SMTP:
return source.SMTP().SkipVerify return source.SMTP().SkipVerify
} }
@ -230,7 +231,7 @@ func DeleteSource(source *LoginSource) error {
// It returns the same LoginUserPlain semantic. // It returns the same LoginUserPlain semantic.
func LoginUserLDAPSource(u *User, loginName, passwd string, source *LoginSource, autoRegister bool) (*User, error) { func LoginUserLDAPSource(u *User, loginName, passwd string, source *LoginSource, autoRegister bool) (*User, error) {
cfg := source.Cfg.(*LDAPConfig) cfg := source.Cfg.(*LDAPConfig)
directBind := (source.Type == DLDAP) directBind := (source.Type == LOGIN_DLDAP)
name, fn, sn, mail, admin, logged := cfg.SearchEntry(loginName, passwd, directBind) name, fn, sn, mail, admin, logged := cfg.SearchEntry(loginName, passwd, directBind)
if !logged { if !logged {
// User not in LDAP, do nothing // User not in LDAP, do nothing
@ -350,7 +351,7 @@ func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error {
// Query if name/passwd can login against the LDAP directory pool // Query if name/passwd can login against the LDAP directory pool
// Create a local user if success // Create a local user if success
// Return the same LoginUserPlain semantic // Return the same LoginUserPlain semantic
func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTPConfig, autoRegister bool) (*User, error) { func LoginUserSMTPSource(u *User, name, passwd string, sourceID int64, cfg *SMTPConfig, autoRegister bool) (*User, error) {
// Verify allowed domains. // Verify allowed domains.
if len(cfg.AllowedDomains) > 0 { if len(cfg.AllowedDomains) > 0 {
idx := strings.Index(name, "@") idx := strings.Index(name, "@")
@ -371,7 +372,11 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP
} }
if err := SMTPAuth(auth, cfg); err != nil { if err := SMTPAuth(auth, cfg); err != nil {
if strings.Contains(err.Error(), "Username and Password not accepted") { // Check standard error format first,
// then fallback to worse case.
tperr, ok := err.(*textproto.Error)
if (ok && tperr.Code == 535) ||
strings.Contains(err.Error(), "Username and Password not accepted") {
return nil, ErrUserNotExist{0, name} return nil, ErrUserNotExist{0, name}
} }
return nil, err return nil, err
@ -390,8 +395,8 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP
u = &User{ u = &User{
LowerName: strings.ToLower(loginName), LowerName: strings.ToLower(loginName),
Name: strings.ToLower(loginName), Name: strings.ToLower(loginName),
LoginType: SMTP, LoginType: LOGIN_SMTP,
LoginSource: sourceId, LoginSource: sourceID,
LoginName: name, LoginName: name,
IsActive: true, IsActive: true,
Passwd: passwd, Passwd: passwd,
@ -411,7 +416,7 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP
// Query if name/passwd can login against PAM // Query if name/passwd can login against PAM
// Create a local user if success // Create a local user if success
// Return the same LoginUserPlain semantic // Return the same LoginUserPlain semantic
func LoginUserPAMSource(u *User, name, passwd string, sourceId int64, cfg *PAMConfig, autoRegister bool) (*User, error) { func LoginUserPAMSource(u *User, name, passwd string, sourceID int64, cfg *PAMConfig, autoRegister bool) (*User, error) {
if err := pam.PAMAuth(cfg.ServiceName, name, passwd); err != nil { if err := pam.PAMAuth(cfg.ServiceName, name, passwd); err != nil {
if strings.Contains(err.Error(), "Authentication failure") { if strings.Contains(err.Error(), "Authentication failure") {
return nil, ErrUserNotExist{0, name} return nil, ErrUserNotExist{0, name}
@ -427,8 +432,8 @@ func LoginUserPAMSource(u *User, name, passwd string, sourceId int64, cfg *PAMCo
u = &User{ u = &User{
LowerName: strings.ToLower(name), LowerName: strings.ToLower(name),
Name: name, Name: name,
LoginType: PAM, LoginType: LOGIN_PAM,
LoginSource: sourceId, LoginSource: sourceID,
LoginName: name, LoginName: name,
IsActive: true, IsActive: true,
Passwd: passwd, Passwd: passwd,
@ -443,11 +448,11 @@ func ExternalUserLogin(u *User, name, passwd string, source *LoginSource, autoRe
} }
switch source.Type { switch source.Type {
case LDAP, DLDAP: case LOGIN_LDAP, LOGIN_DLDAP:
return LoginUserLDAPSource(u, name, passwd, source, autoRegister) return LoginUserLDAPSource(u, name, passwd, source, autoRegister)
case SMTP: case LOGIN_SMTP:
return LoginUserSMTPSource(u, name, passwd, source.ID, source.Cfg.(*SMTPConfig), autoRegister) return LoginUserSMTPSource(u, name, passwd, source.ID, source.Cfg.(*SMTPConfig), autoRegister)
case PAM: case LOGIN_PAM:
return LoginUserPAMSource(u, name, passwd, source.ID, source.Cfg.(*PAMConfig), autoRegister) return LoginUserPAMSource(u, name, passwd, source.ID, source.Cfg.(*PAMConfig), autoRegister)
} }
@ -470,7 +475,7 @@ func UserSignIn(uname, passwd string) (*User, error) {
if userExists { if userExists {
switch u.LoginType { switch u.LoginType {
case NOTYPE, PLAIN: case LOGIN_NOTYPE, LOGIN_PLAIN:
if u.ValidatePassword(passwd) { if u.ValidatePassword(passwd) {
return u, nil return u, nil
} }

336
models/migrations/migrations.go

@ -13,18 +13,18 @@ import (
"path" "path"
"path/filepath" "path/filepath"
"strings" "strings"
"time"
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"gopkg.in/ini.v1" "gopkg.in/ini.v1"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
gouuid "github.com/gogits/gogs/modules/uuid" gouuid "github.com/gogits/gogs/modules/uuid"
) )
const _MIN_DB_VER = 0 const _MIN_DB_VER = 4
type Migration interface { type Migration interface {
Description() string Description() string
@ -58,16 +58,13 @@ type Version struct {
// If you want to "retire" a migration, remove it from the top of the list and // If you want to "retire" a migration, remove it from the top of the list and
// update _MIN_VER_DB accordingly // update _MIN_VER_DB accordingly
var migrations = []Migration{ var migrations = []Migration{
NewMigration("generate collaboration from access", accessToCollaboration), // V0 -> V1:v0.5.13
NewMigration("make authorize 4 if team is owners", ownerTeamUpdate), // V1 -> V2:v0.5.13
NewMigration("refactor access table to use id's", accessRefactor), // V2 -> V3:v0.5.13
NewMigration("generate team-repo from team", teamToTeamRepo), // V3 -> V4:v0.5.13
NewMigration("fix locale file load panic", fixLocaleFileLoadPanic), // V4 -> V5:v0.6.0 NewMigration("fix locale file load panic", fixLocaleFileLoadPanic), // V4 -> V5:v0.6.0
NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix), // V5 -> V6:v0.6.3 NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix), // V5 -> V6:v0.6.3
NewMigration("generate issue-label from issue", issueToIssueLabel), // V6 -> V7:v0.6.4 NewMigration("generate issue-label from issue", issueToIssueLabel), // V6 -> V7:v0.6.4
NewMigration("refactor attachment table", attachmentRefactor), // V7 -> V8:v0.6.4 NewMigration("refactor attachment table", attachmentRefactor), // V7 -> V8:v0.6.4
NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16 NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16
NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20 NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20
NewMigration("generate rands and salt for organizations", generateOrgRandsAndSalt), // V10 -> V11:v0.8.5
} }
// Migrate database to current version // Migrate database to current version
@ -81,24 +78,9 @@ func Migrate(x *xorm.Engine) error {
if err != nil { if err != nil {
return fmt.Errorf("get: %v", err) return fmt.Errorf("get: %v", err)
} else if !has { } else if !has {
// If the user table does not exist it is a fresh installation and we // If the version record does not exist we think
// can skip all migrations. // it is a fresh installation and we can skip all migrations.
needsMigration, err := x.IsTableExist("user")
if err != nil {
return err
}
if needsMigration {
isEmpty, err := x.IsTableEmpty("user")
if err != nil {
return err
}
// If the user table is empty it is a fresh installation and we can
// skip all migrations.
needsMigration = !isEmpty
}
if !needsMigration {
currentVersion.Version = int64(_MIN_DB_VER + len(migrations)) currentVersion.Version = int64(_MIN_DB_VER + len(migrations))
}
if _, err = x.InsertOne(currentVersion); err != nil { if _, err = x.InsertOne(currentVersion); err != nil {
return fmt.Errorf("insert: %v", err) return fmt.Errorf("insert: %v", err)
@ -107,7 +89,8 @@ func Migrate(x *xorm.Engine) error {
v := currentVersion.Version v := currentVersion.Version
if _MIN_DB_VER > v { if _MIN_DB_VER > v {
log.Fatal(4, "Gogs no longer supports auto-migration from your previously installed version. Please try to upgrade to a lower version first, then upgrade to current version.") log.Fatal(4, `Gogs no longer supports auto-migration from your previously installed version.
Please try to upgrade to a lower version (>= v0.6.0) first, then upgrade to current version.`)
return nil return nil
} }
@ -137,276 +120,6 @@ func sessionRelease(sess *xorm.Session) {
sess.Close() sess.Close()
} }
func accessToCollaboration(x *xorm.Engine) (err error) {
type Collaboration struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
Created time.Time
}
if err = x.Sync(new(Collaboration)); err != nil {
return fmt.Errorf("sync: %v", err)
}
results, err := x.Query("SELECT u.id AS `uid`, a.repo_name AS `repo`, a.mode AS `mode`, a.created as `created` FROM `access` a JOIN `user` u ON a.user_name=u.lower_name")
if err != nil {
if strings.Contains(err.Error(), "no such column") {
return nil
}
return err
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
offset := strings.Split(time.Now().String(), " ")[2]
for _, result := range results {
mode := com.StrTo(result["mode"]).MustInt64()
// Collaborators must have write access.
if mode < 2 {
continue
}
userID := com.StrTo(result["uid"]).MustInt64()
repoRefName := string(result["repo"])
var created time.Time
switch {
case setting.UseSQLite3:
created, _ = time.Parse(time.RFC3339, string(result["created"]))
case setting.UseMySQL:
created, _ = time.Parse("2006-01-02 15:04:05-0700", string(result["created"])+offset)
case setting.UsePostgreSQL:
created, _ = time.Parse("2006-01-02T15:04:05Z-0700", string(result["created"])+offset)
}
// find owner of repository
parts := strings.SplitN(repoRefName, "/", 2)
ownerName := parts[0]
repoName := parts[1]
results, err := sess.Query("SELECT u.id as `uid`, ou.uid as `memberid` FROM `user` u LEFT JOIN org_user ou ON ou.org_id=u.id WHERE u.lower_name=?", ownerName)
if err != nil {
return err
}
if len(results) < 1 {
continue
}
ownerID := com.StrTo(results[0]["uid"]).MustInt64()
if ownerID == userID {
continue
}
// test if user is member of owning organization
isMember := false
for _, member := range results {
memberID := com.StrTo(member["memberid"]).MustInt64()
// We can skip all cases that a user is member of the owning organization
if memberID == userID {
isMember = true
}
}
if isMember {
continue
}
results, err = sess.Query("SELECT id FROM `repository` WHERE owner_id=? AND lower_name=?", ownerID, repoName)
if err != nil {
return err
} else if len(results) < 1 {
continue
}
collaboration := &Collaboration{
UserID: userID,
RepoID: com.StrTo(results[0]["id"]).MustInt64(),
}
has, err := sess.Get(collaboration)
if err != nil {
return err
} else if has {
continue
}
collaboration.Created = created
if _, err = sess.InsertOne(collaboration); err != nil {
return err
}
}
return sess.Commit()
}
func ownerTeamUpdate(x *xorm.Engine) (err error) {
if _, err := x.Exec("UPDATE `team` SET authorize=4 WHERE lower_name=?", "owners"); err != nil {
return fmt.Errorf("update owner team table: %v", err)
}
return nil
}
func accessRefactor(x *xorm.Engine) (err error) {
type (
AccessMode int
Access struct {
ID int64 `xorm:"pk autoincr"`
UserID int64 `xorm:"UNIQUE(s)"`
RepoID int64 `xorm:"UNIQUE(s)"`
Mode AccessMode
}
UserRepo struct {
UserID int64
RepoID int64
}
)
// We consiously don't start a session yet as we make only reads for now, no writes
accessMap := make(map[UserRepo]AccessMode, 50)
results, err := x.Query("SELECT r.id AS `repo_id`, r.is_private AS `is_private`, r.owner_id AS `owner_id`, u.type AS `owner_type` FROM `repository` r LEFT JOIN `user` u ON r.owner_id=u.id")
if err != nil {
return fmt.Errorf("select repositories: %v", err)
}
for _, repo := range results {
repoID := com.StrTo(repo["repo_id"]).MustInt64()
isPrivate := com.StrTo(repo["is_private"]).MustInt() > 0
ownerID := com.StrTo(repo["owner_id"]).MustInt64()
ownerIsOrganization := com.StrTo(repo["owner_type"]).MustInt() > 0
results, err := x.Query("SELECT `user_id` FROM `collaboration` WHERE repo_id=?", repoID)
if err != nil {
return fmt.Errorf("select collaborators: %v", err)
}
for _, user := range results {
userID := com.StrTo(user["user_id"]).MustInt64()
accessMap[UserRepo{userID, repoID}] = 2 // WRITE ACCESS
}
if !ownerIsOrganization {
continue
}
// The minimum level to add a new access record,
// because public repository has implicit open access.
minAccessLevel := AccessMode(0)
if !isPrivate {
minAccessLevel = 1
}
repoString := "$" + string(repo["repo_id"]) + "|"
results, err = x.Query("SELECT `id`,`authorize`,`repo_ids` FROM `team` WHERE org_id=? AND authorize>? ORDER BY `authorize` ASC", ownerID, int(minAccessLevel))
if err != nil {
if strings.Contains(err.Error(), "no such column") {
return nil
}
return fmt.Errorf("select teams from org: %v", err)
}
for _, team := range results {
if !strings.Contains(string(team["repo_ids"]), repoString) {
continue
}
teamID := com.StrTo(team["id"]).MustInt64()
mode := AccessMode(com.StrTo(team["authorize"]).MustInt())
results, err := x.Query("SELECT `uid` FROM `team_user` WHERE team_id=?", teamID)
if err != nil {
return fmt.Errorf("select users from team: %v", err)
}
for _, user := range results {
userID := com.StrTo(user["uid"]).MustInt64()
accessMap[UserRepo{userID, repoID}] = mode
}
}
}
// Drop table can't be in a session (at least not in sqlite)
if _, err = x.Exec("DROP TABLE `access`"); err != nil {
return fmt.Errorf("drop access table: %v", err)
}
// Now we start writing so we make a session
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = sess.Sync2(new(Access)); err != nil {
return fmt.Errorf("sync: %v", err)
}
accesses := make([]*Access, 0, len(accessMap))
for ur, mode := range accessMap {
accesses = append(accesses, &Access{UserID: ur.UserID, RepoID: ur.RepoID, Mode: mode})
}
if _, err = sess.Insert(accesses); err != nil {
return fmt.Errorf("insert accesses: %v", err)
}
return sess.Commit()
}
func teamToTeamRepo(x *xorm.Engine) error {
type TeamRepo struct {
ID int64 `xorm:"pk autoincr"`
OrgID int64 `xorm:"INDEX"`
TeamID int64 `xorm:"UNIQUE(s)"`
RepoID int64 `xorm:"UNIQUE(s)"`
}
teamRepos := make([]*TeamRepo, 0, 50)
results, err := x.Query("SELECT `id`,`org_id`,`repo_ids` FROM `team`")
if err != nil {
if strings.Contains(err.Error(), "no such column") {
return nil
}
return fmt.Errorf("select teams: %v", err)
}
for _, team := range results {
orgID := com.StrTo(team["org_id"]).MustInt64()
teamID := com.StrTo(team["id"]).MustInt64()
// #1032: legacy code can have duplicated IDs for same repository.
mark := make(map[int64]bool)
for _, idStr := range strings.Split(string(team["repo_ids"]), "|") {
repoID := com.StrTo(strings.TrimPrefix(idStr, "$")).MustInt64()
if repoID == 0 || mark[repoID] {
continue
}
mark[repoID] = true
teamRepos = append(teamRepos, &TeamRepo{
OrgID: orgID,
TeamID: teamID,
RepoID: repoID,
})
}
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = sess.Sync2(new(TeamRepo)); err != nil {
return fmt.Errorf("sync2: %v", err)
} else if _, err = sess.Insert(teamRepos); err != nil {
return fmt.Errorf("insert team-repos: %v", err)
}
return sess.Commit()
}
func fixLocaleFileLoadPanic(_ *xorm.Engine) error { func fixLocaleFileLoadPanic(_ *xorm.Engine) error {
cfg, err := ini.Load(setting.CustomConf) cfg, err := ini.Load(setting.CustomConf)
if err != nil { if err != nil {
@ -494,7 +207,8 @@ func issueToIssueLabel(x *xorm.Engine) error {
issueLabels := make([]*IssueLabel, 0, 50) issueLabels := make([]*IssueLabel, 0, 50)
results, err := x.Query("SELECT `id`,`label_ids` FROM `issue`") results, err := x.Query("SELECT `id`,`label_ids` FROM `issue`")
if err != nil { if err != nil {
if strings.Contains(err.Error(), "no such column") { if strings.Contains(err.Error(), "no such column") ||
strings.Contains(err.Error(), "Unknown column") {
return nil return nil
} }
return fmt.Errorf("select issues: %v", err) return fmt.Errorf("select issues: %v", err)
@ -653,6 +367,9 @@ func renamePullRequestFields(x *xorm.Engine) (err error) {
Index: com.StrTo(pr["pull_index"]).MustInt64(), Index: com.StrTo(pr["pull_index"]).MustInt64(),
HeadBranch: string(pr["head_barcnh"]), HeadBranch: string(pr["head_barcnh"]),
} }
if pull.Index == 0 {
continue
}
if _, err = sess.Id(pull.ID).Update(pull); err != nil { if _, err = sess.Id(pull.ID).Update(pull); err != nil {
return err return err
} }
@ -707,3 +424,32 @@ func cleanUpMigrateRepoInfo(x *xorm.Engine) (err error) {
return nil return nil
} }
func generateOrgRandsAndSalt(x *xorm.Engine) (err error) {
type User struct {
ID int64 `xorm:"pk autoincr"`
Rands string `xorm:"VARCHAR(10)"`
Salt string `xorm:"VARCHAR(10)"`
}
orgs := make([]*User, 0, 10)
if err = x.Where("type=1").And("rands=''").Find(&orgs); err != nil {
return fmt.Errorf("select all organizations: %v", err)
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
for _, org := range orgs {
org.Rands = base.GetRandomString(10)
org.Salt = base.GetRandomString(10)
if _, err = sess.Id(org.ID).Update(org); err != nil {
return err
}
}
return sess.Commit()
}

3
models/org.go

@ -108,7 +108,10 @@ func CreateOrganization(org, owner *User) (err error) {
org.LowerName = strings.ToLower(org.Name) org.LowerName = strings.ToLower(org.Name)
org.FullName = org.Name org.FullName = org.Name
org.Rands = GetUserSalt()
org.Salt = GetUserSalt()
org.UseCustomAvatar = true org.UseCustomAvatar = true
org.MaxRepoCreation = -1
org.NumTeams = 1 org.NumTeams = 1
org.NumMembers = 1 org.NumMembers = 1

55
models/pull.go

@ -14,7 +14,9 @@ import (
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"github.com/gogits/gogs/modules/git" "github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/process" "github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
@ -124,6 +126,12 @@ func (pr *PullRequest) CanAutoMerge() bool {
// Merge merges pull request to base repository. // Merge merges pull request to base repository.
func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error) { func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error) {
if err = pr.GetHeadRepo(); err != nil {
return fmt.Errorf("GetHeadRepo: %v", err)
} else if err = pr.GetBaseRepo(); err != nil {
return fmt.Errorf("GetBaseRepo: %v", err)
}
sess := x.NewSession() sess := x.NewSession()
defer sessionRelease(sess) defer sessionRelease(sess)
if err = sess.Begin(); err != nil { if err = sess.Begin(); err != nil {
@ -134,18 +142,14 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
return fmt.Errorf("Issue.changeStatus: %v", err) return fmt.Errorf("Issue.changeStatus: %v", err)
} }
if err = pr.getHeadRepo(sess); err != nil {
return fmt.Errorf("getHeadRepo: %v", err)
}
headRepoPath := RepoPath(pr.HeadUserName, pr.HeadRepo.Name) headRepoPath := RepoPath(pr.HeadUserName, pr.HeadRepo.Name)
headGitRepo, err := git.OpenRepository(headRepoPath) headGitRepo, err := git.OpenRepository(headRepoPath)
if err != nil { if err != nil {
return fmt.Errorf("OpenRepository: %v", err) return fmt.Errorf("OpenRepository: %v", err)
} }
pr.MergedCommitID, err = headGitRepo.GetCommitIdOfBranch(pr.HeadBranch) pr.MergedCommitID, err = headGitRepo.GetBranchCommitID(pr.HeadBranch)
if err != nil { if err != nil {
return fmt.Errorf("GetCommitIdOfBranch: %v", err) return fmt.Errorf("GetBranchCommitID: %v", err)
} }
if err = mergePullRequestAction(sess, doer, pr.Issue.Repo, pr.Issue); err != nil { if err = mergePullRequestAction(sess, doer, pr.Issue.Repo, pr.Issue); err != nil {
@ -213,7 +217,38 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
return fmt.Errorf("git push: %s", stderr) return fmt.Errorf("git push: %s", stderr)
} }
return sess.Commit() if err = sess.Commit(); err != nil {
return fmt.Errorf("Commit: %v", err)
}
// Compose commit repository action
l, err := headGitRepo.CommitsBetweenIDs(pr.MergedCommitID, pr.MergeBase)
if err != nil {
return fmt.Errorf("CommitsBetween: %v", err)
}
p := &api.PushPayload{
Ref: "refs/heads/" + pr.BaseBranch,
Before: pr.MergeBase,
After: pr.MergedCommitID,
CompareUrl: setting.AppUrl + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID),
Commits: ListToPushCommits(l).ToApiPayloadCommits(pr.BaseRepo.FullRepoLink()),
Repo: pr.BaseRepo.ComposePayload(),
Pusher: &api.PayloadAuthor{
Name: pr.HeadRepo.MustOwner().DisplayName(),
Email: pr.HeadRepo.MustOwner().Email,
UserName: pr.HeadRepo.MustOwner().Name,
},
Sender: &api.PayloadUser{
UserName: doer.Name,
ID: doer.Id,
AvatarUrl: setting.AppUrl + doer.RelAvatarLink(),
},
}
if err = PrepareWebhooks(pr.BaseRepo, HOOK_EVENT_PUSH, p); err != nil {
return fmt.Errorf("PrepareWebhooks: %v", err)
}
go HookQueue.Add(pr.BaseRepo.ID)
return nil
} }
// patchConflicts is a list of conflit description from Git. // patchConflicts is a list of conflit description from Git.
@ -411,8 +446,6 @@ func (pr *PullRequest) UpdatePatch() (err error) {
if err = pr.GetBaseRepo(); err != nil { if err = pr.GetBaseRepo(); err != nil {
return fmt.Errorf("GetBaseRepo: %v", err) return fmt.Errorf("GetBaseRepo: %v", err)
} else if err = pr.BaseRepo.GetOwner(); err != nil {
return fmt.Errorf("GetOwner: %v", err)
} }
headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
@ -422,7 +455,7 @@ func (pr *PullRequest) UpdatePatch() (err error) {
// Add a temporary remote. // Add a temporary remote.
tmpRemote := com.ToStr(time.Now().UnixNano()) tmpRemote := com.ToStr(time.Now().UnixNano())
if err = headGitRepo.AddRemote(tmpRemote, RepoPath(pr.BaseRepo.Owner.Name, pr.BaseRepo.Name)); err != nil { if err = headGitRepo.AddRemote(tmpRemote, RepoPath(pr.BaseRepo.MustOwner().Name, pr.BaseRepo.Name), true); err != nil {
return fmt.Errorf("AddRemote: %v", err) return fmt.Errorf("AddRemote: %v", err)
} }
defer func() { defer func() {

21
models/release.go

@ -12,7 +12,8 @@ import (
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"github.com/gogits/gogs/modules/git" "github.com/gogits/git-module"
"github.com/gogits/gogs/modules/process" "github.com/gogits/gogs/modules/process"
) )
@ -27,8 +28,8 @@ type Release struct {
Target string Target string
Title string Title string
Sha1 string `xorm:"VARCHAR(40)"` Sha1 string `xorm:"VARCHAR(40)"`
NumCommits int NumCommits int64
NumCommitsBehind int `xorm:"-"` NumCommitsBehind int64 `xorm:"-"`
Note string `xorm:"TEXT"` Note string `xorm:"TEXT"`
IsDraft bool `xorm:"NOT NULL DEFAULT false"` IsDraft bool `xorm:"NOT NULL DEFAULT false"`
IsPrerelease bool IsPrerelease bool
@ -51,31 +52,27 @@ func IsReleaseExist(repoID int64, tagName string) (bool, error) {
return x.Get(&Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)}) return x.Get(&Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)})
} }
func init() {
git.GetVersion()
}
func createTag(gitRepo *git.Repository, rel *Release) error { func createTag(gitRepo *git.Repository, rel *Release) error {
// Only actual create when publish. // Only actual create when publish.
if !rel.IsDraft { if !rel.IsDraft {
if !gitRepo.IsTagExist(rel.TagName) { if !gitRepo.IsTagExist(rel.TagName) {
commit, err := gitRepo.GetCommitOfBranch(rel.Target) commit, err := gitRepo.GetBranchCommit(rel.Target)
if err != nil { if err != nil {
return err return fmt.Errorf("GetBranchCommit: %v", err)
} }
if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil { if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
return err return err
} }
} else { } else {
commit, err := gitRepo.GetCommitOfTag(rel.TagName) commit, err := gitRepo.GetTagCommit(rel.TagName)
if err != nil { if err != nil {
return err return fmt.Errorf("GetTagCommit: %v", err)
} }
rel.NumCommits, err = commit.CommitsCount() rel.NumCommits, err = commit.CommitsCount()
if err != nil { if err != nil {
return err return fmt.Errorf("CommitsCount: %v", err)
} }
} }
} }

42
models/repo.go

@ -27,7 +27,7 @@ import (
"github.com/mcuadros/go-version" "github.com/mcuadros/go-version"
"gopkg.in/ini.v1" "gopkg.in/ini.v1"
"github.com/gogits/git-shell" "github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client" api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
@ -98,7 +98,7 @@ func NewRepoContext() {
} }
// Check Git version. // Check Git version.
gitVer, err := git.Version() gitVer, err := git.BinVersion()
if err != nil { if err != nil {
log.Fatal(4, "Fail to get Git version: %v", err) log.Fatal(4, "Fail to get Git version: %v", err)
} }
@ -129,6 +129,8 @@ func NewRepoContext() {
log.Fatal(4, "Fail to execute 'git config --global core.quotepath false': %s", stderr) log.Fatal(4, "Fail to execute 'git config --global core.quotepath false': %s", stderr)
} }
// Clean up temporary data.
os.RemoveAll(filepath.Join(setting.AppDataPath, "tmp"))
} }
// Repository represents a git repository. // Repository represents a git repository.
@ -164,6 +166,8 @@ type Repository struct {
// Advanced settings // Advanced settings
EnableWiki bool `xorm:"NOT NULL DEFAULT true"` EnableWiki bool `xorm:"NOT NULL DEFAULT true"`
EnableExternalWiki bool
ExternalWikiURL string
EnableIssues bool `xorm:"NOT NULL DEFAULT true"` EnableIssues bool `xorm:"NOT NULL DEFAULT true"`
EnableExternalTracker bool EnableExternalTracker bool
ExternalTrackerFormat string ExternalTrackerFormat string
@ -309,6 +313,10 @@ func (repo *Repository) RepoLink() string {
return setting.AppSubUrl + "/" + repo.MustOwner().Name + "/" + repo.Name return setting.AppSubUrl + "/" + repo.MustOwner().Name + "/" + repo.Name
} }
func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) string {
return fmt.Sprintf("%s/%s/compare/%s...%s", repo.MustOwner().Name, repo.Name, oldCommitID, newCommitID)
}
func (repo *Repository) FullRepoLink() string { func (repo *Repository) FullRepoLink() string {
return setting.AppUrl + repo.MustOwner().Name + "/" + repo.Name return setting.AppUrl + repo.MustOwner().Name + "/" + repo.Name
} }
@ -896,6 +904,10 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
// CreateRepository creates a repository for given user or organization. // CreateRepository creates a repository for given user or organization.
func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error) { func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error) {
if !u.CanCreateRepo() {
return nil, ErrReachLimitOfRepo{u.MaxRepoCreation}
}
repo := &Repository{ repo := &Repository{
OwnerID: u.Id, OwnerID: u.Id,
Owner: u, Owner: u,
@ -1291,7 +1303,8 @@ func DeleteRepository(uid, repoID int64) error {
} }
} }
wikiPath := repo.WikiPath() wikiPaths := []string{repo.WikiPath(), repo.LocalWikiPath()}
for _, wikiPath := range wikiPaths {
if err = os.RemoveAll(wikiPath); err != nil { if err = os.RemoveAll(wikiPath); err != nil {
desc := fmt.Sprintf("delete repository wiki [%s]: %v", wikiPath, err) desc := fmt.Sprintf("delete repository wiki [%s]: %v", wikiPath, err)
log.Warn(desc) log.Warn(desc)
@ -1299,6 +1312,7 @@ func DeleteRepository(uid, repoID int64) error {
log.Error(4, "CreateRepositoryNotice: %v", err) log.Error(4, "CreateRepositoryNotice: %v", err)
} }
} }
}
// Remove attachment files. // Remove attachment files.
for i := range attachmentPaths { for i := range attachmentPaths {
@ -1583,13 +1597,11 @@ func GitFsck() {
log.Trace("Doing: GitFsck") log.Trace("Doing: GitFsck")
args := append([]string{"fsck"}, setting.Cron.RepoHealthCheck.Args...)
if err := x.Where("id>0").Iterate(new(Repository), if err := x.Where("id>0").Iterate(new(Repository),
func(idx int, bean interface{}) error { func(idx int, bean interface{}) error {
repo := bean.(*Repository) repo := bean.(*Repository)
repoPath := repo.RepoPath() repoPath := repo.RepoPath()
_, _, err := process.ExecDir(-1, repoPath, "Repository health check", "git", args...) if err := git.Fsck(repoPath, setting.Cron.RepoHealthCheck.Timeout, setting.Cron.RepoHealthCheck.Args...); err != nil {
if err != nil {
desc := fmt.Sprintf("Fail to health check repository(%s)", repoPath) desc := fmt.Sprintf("Fail to health check repository(%s)", repoPath)
log.Warn(desc) log.Warn(desc)
if err = CreateRepositoryNotice(desc); err != nil { if err = CreateRepositoryNotice(desc); err != nil {
@ -1878,8 +1890,13 @@ func GetWatchers(repoID int64) ([]*Watch, error) {
// Repository.GetWatchers returns range of users watching given repository. // Repository.GetWatchers returns range of users watching given repository.
func (repo *Repository) GetWatchers(page int) ([]*User, error) { func (repo *Repository) GetWatchers(page int) ([]*User, error) {
users := make([]*User, 0, ItemsPerPage) users := make([]*User, 0, ItemsPerPage)
return users, x.Limit(ItemsPerPage, (page-1)*ItemsPerPage). sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("watch.repo_id=?", repo.ID)
Where("repo_id=?", repo.ID).Join("LEFT", "watch", "user.id=watch.user_id").Find(&users) if setting.UsePostgreSQL {
sess = sess.Join("LEFT", "watch", `"user".id=watch.user_id`)
} else {
sess = sess.Join("LEFT", "watch", "user.id=watch.user_id")
}
return users, sess.Find(&users)
} }
func notifyWatchers(e Engine, act *Action) error { func notifyWatchers(e Engine, act *Action) error {
@ -1961,8 +1978,13 @@ func IsStaring(uid, repoId int64) bool {
func (repo *Repository) GetStargazers(page int) ([]*User, error) { func (repo *Repository) GetStargazers(page int) ([]*User, error) {
users := make([]*User, 0, ItemsPerPage) users := make([]*User, 0, ItemsPerPage)
return users, x.Limit(ItemsPerPage, (page-1)*ItemsPerPage). sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("star.repo_id=?", repo.ID)
Where("repo_id=?", repo.ID).Join("LEFT", "star", "user.id=star.uid").Find(&users) if setting.UsePostgreSQL {
sess = sess.Join("LEFT", "star", `"user".id=star.uid`)
} else {
sess = sess.Join("LEFT", "star", "user.id=star.uid")
}
return users, sess.Find(&users)
} }
// ___________ __ // ___________ __

10
models/publickey.go → models/ssh_key.go

@ -299,6 +299,11 @@ func addKey(e Engine, key *PublicKey) (err error) {
if _, err = e.Insert(key); err != nil { if _, err = e.Insert(key); err != nil {
return err return err
} }
// Don't need to rewrite this file if builtin SSH server is enabled.
if setting.StartSSHServer {
return nil
}
return saveAuthorizedKeyFile(key) return saveAuthorizedKeyFile(key)
} }
@ -439,6 +444,11 @@ func deletePublicKey(e *xorm.Session, keyID int64) error {
return err return err
} }
// Don't need to rewrite this file if builtin SSH server is enabled.
if setting.StartSSHServer {
return nil
}
fpath := filepath.Join(SSHPath, "authorized_keys") fpath := filepath.Join(SSHPath, "authorized_keys")
tmpPath := filepath.Join(SSHPath, "authorized_keys.tmp") tmpPath := filepath.Join(SSHPath, "authorized_keys.tmp")
if err = rewriteAuthorizedKeys(key, fpath, tmpPath); err != nil { if err = rewriteAuthorizedKeys(key, fpath, tmpPath); err != nil {

43
models/update.go

@ -10,7 +10,8 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"github.com/gogits/gogs/modules/git" "github.com/gogits/git-module"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
) )
@ -46,6 +47,24 @@ func DeleteUpdateTaskByUUID(uuid string) error {
return err return err
} }
func ListToPushCommits(l *list.List) *PushCommits {
commits := make([]*PushCommit, 0)
var actEmail string
for e := l.Front(); e != nil; e = e.Next() {
commit := e.Value.(*git.Commit)
if actEmail == "" {
actEmail = commit.Committer.Email
}
commits = append(commits,
&PushCommit{commit.ID.String(),
commit.Message(),
commit.Author.Email,
commit.Author.Name,
})
}
return &PushCommits{l.Len(), commits, "", nil}
}
func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName string, userID int64) error { func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName string, userID int64) error {
isNew := strings.HasPrefix(oldCommitID, "0000000") isNew := strings.HasPrefix(oldCommitID, "0000000")
if isNew && if isNew &&
@ -116,7 +135,7 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName
// Push new branch. // Push new branch.
var l *list.List var l *list.List
if isNew { if isNew {
l, err = newCommit.CommitsBefore() l, err = newCommit.CommitsBeforeLimit(10)
if err != nil { if err != nil {
return fmt.Errorf("CommitsBefore: %v", err) return fmt.Errorf("CommitsBefore: %v", err)
} }
@ -131,24 +150,8 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName
return fmt.Errorf("runUpdate.Commit repoId: %v", err) return fmt.Errorf("runUpdate.Commit repoId: %v", err)
} }
// Push commits. if err = CommitRepoAction(userID, user.Id, userName, user.Email,
commits := make([]*PushCommit, 0) repo.ID, repoUserName, repoName, refName, ListToPushCommits(l), oldCommitID, newCommitID); err != nil {
var actEmail string
for e := l.Front(); e != nil; e = e.Next() {
commit := e.Value.(*git.Commit)
if actEmail == "" {
actEmail = commit.Committer.Email
}
commits = append(commits,
&PushCommit{commit.ID.String(),
commit.Message(),
commit.Author.Email,
commit.Author.Name,
})
}
if err = CommitRepoAction(userID, user.Id, userName, actEmail,
repo.ID, repoUserName, repoName, refName, &PushCommits{l.Len(), commits, "", nil}, oldCommitID, newCommitID); err != nil {
return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err) return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
} }
return nil return nil

84
models/user.go

@ -25,11 +25,10 @@ import (
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"github.com/nfnt/resize" "github.com/nfnt/resize"
"github.com/gogits/git-shell" "github.com/gogits/git-module"
"github.com/gogits/gogs/modules/avatar" "github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
oldgit "github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
@ -76,6 +75,8 @@ type User struct {
// Remember visibility choice for convenience, true for private // Remember visibility choice for convenience, true for private
LastRepoVisibility bool LastRepoVisibility bool
// Maximum repository creation limit, -1 means use gloabl default
MaxRepoCreation int `xorm:"NOT NULL DEFAULT -1"`
// Permissions. // Permissions.
IsActive bool IsActive bool
@ -102,6 +103,12 @@ type User struct {
Members []*User `xorm:"-"` Members []*User `xorm:"-"`
} }
func (u *User) BeforeUpdate() {
if u.MaxRepoCreation < -1 {
u.MaxRepoCreation = -1
}
}
func (u *User) AfterSet(colName string, _ xorm.Cell) { func (u *User) AfterSet(colName string, _ xorm.Cell) {
switch colName { switch colName {
case "full_name": case "full_name":
@ -111,12 +118,34 @@ func (u *User) AfterSet(colName string, _ xorm.Cell) {
} }
} }
// returns true if user login type is LOGIN_PLAIN.
func (u *User) IsLocal() bool {
return u.LoginType <= LOGIN_PLAIN
}
// HasForkedRepo checks if user has already forked a repository with given ID. // HasForkedRepo checks if user has already forked a repository with given ID.
func (u *User) HasForkedRepo(repoID int64) bool { func (u *User) HasForkedRepo(repoID int64) bool {
_, has := HasForkedRepo(u.Id, repoID) _, has := HasForkedRepo(u.Id, repoID)
return has return has
} }
func (u *User) RepoCreationNum() int {
if u.MaxRepoCreation <= -1 {
return setting.Repository.MaxCreationLimit
}
return u.MaxRepoCreation
}
func (u *User) CanCreateRepo() bool {
if u.MaxRepoCreation <= -1 {
if setting.Repository.MaxCreationLimit <= -1 {
return true
}
return u.NumRepos < setting.Repository.MaxCreationLimit
}
return u.NumRepos < u.MaxRepoCreation
}
// CanEditGitHook returns true if user can edit Git hooks. // CanEditGitHook returns true if user can edit Git hooks.
func (u *User) CanEditGitHook() bool { func (u *User) CanEditGitHook() bool {
return u.IsAdmin || u.AllowGitHook return u.IsAdmin || u.AllowGitHook
@ -446,6 +475,7 @@ func CreateUser(u *User) (err error) {
u.Rands = GetUserSalt() u.Rands = GetUserSalt()
u.Salt = GetUserSalt() u.Salt = GetUserSalt()
u.EncodePasswd() u.EncodePasswd()
u.MaxRepoCreation = -1
sess := x.NewSession() sess := x.NewSession()
defer sess.Close() defer sess.Close()
@ -858,7 +888,7 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
} }
func AddEmailAddress(email *EmailAddress) error { func AddEmailAddress(email *EmailAddress) error {
email.Email = strings.ToLower(email.Email) email.Email = strings.ToLower(strings.TrimSpace(email.Email))
used, err := IsEmailUsed(email.Email) used, err := IsEmailUsed(email.Email)
if err != nil { if err != nil {
return err return err
@ -870,6 +900,29 @@ func AddEmailAddress(email *EmailAddress) error {
return err return err
} }
func AddEmailAddresses(emails []*EmailAddress) error {
if len(emails) == 0 {
return nil
}
// Check if any of them has been used
for i := range emails {
emails[i].Email = strings.ToLower(strings.TrimSpace(emails[i].Email))
used, err := IsEmailUsed(emails[i].Email)
if err != nil {
return err
} else if used {
return ErrEmailAlreadyUsed{emails[i].Email}
}
}
if _, err := x.Insert(emails); err != nil {
return fmt.Errorf("Insert: %v", err)
}
return nil
}
func (email *EmailAddress) Activate() error { func (email *EmailAddress) Activate() error {
email.IsActivated = true email.IsActivated = true
if _, err := x.Id(email.ID).AllCols().Update(email); err != nil { if _, err := x.Id(email.ID).AllCols().Update(email); err != nil {
@ -884,20 +937,23 @@ func (email *EmailAddress) Activate() error {
} }
} }
func DeleteEmailAddress(email *EmailAddress) error { func DeleteEmailAddress(email *EmailAddress) (err error) {
has, err := x.Get(email) if email.ID > 0 {
if err != nil { _, err = x.Id(email.ID).Delete(new(EmailAddress))
return err } else {
} else if !has { _, err = x.Where("email=?", email.Email).Delete(new(EmailAddress))
return ErrEmailNotExist
} }
return err
}
if _, err = x.Id(email.ID).Delete(email); err != nil { func DeleteEmailAddresses(emails []*EmailAddress) (err error) {
for i := range emails {
if err = DeleteEmailAddress(emails[i]); err != nil {
return err return err
} }
}
return nil return nil
} }
func MakeEmailPrimary(email *EmailAddress) error { func MakeEmailPrimary(email *EmailAddress) error {
@ -940,11 +996,11 @@ func MakeEmailPrimary(email *EmailAddress) error {
// UserCommit represents a commit with validation of user. // UserCommit represents a commit with validation of user.
type UserCommit struct { type UserCommit struct {
User *User User *User
*oldgit.Commit *git.Commit
} }
// ValidateCommitWithEmail chceck if author's e-mail of commit is corresponsind to a user. // ValidateCommitWithEmail chceck if author's e-mail of commit is corresponsind to a user.
func ValidateCommitWithEmail(c *oldgit.Commit) *User { func ValidateCommitWithEmail(c *git.Commit) *User {
u, err := GetUserByEmail(c.Author.Email) u, err := GetUserByEmail(c.Author.Email)
if err != nil { if err != nil {
return nil return nil
@ -961,7 +1017,7 @@ func ValidateCommitsWithEmails(oldCommits *list.List) *list.List {
e = oldCommits.Front() e = oldCommits.Front()
) )
for e != nil { for e != nil {
c := e.Value.(*oldgit.Commit) c := e.Value.(*git.Commit)
if v, ok := emails[c.Author.Email]; !ok { if v, ok := emails[c.Author.Email]; !ok {
u, _ = GetUserByEmail(c.Author.Email) u, _ = GetUserByEmail(c.Author.Email)

3
models/webhook_slack.go

@ -10,9 +10,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client" api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/git"
) )
type SlackMeta struct { type SlackMeta struct {

2
models/wiki.go

@ -15,7 +15,7 @@ import (
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/gogits/git-shell" "github.com/gogits/git-module"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )

1
modules/auth/admin.go

@ -31,6 +31,7 @@ type AdminEditUserForm struct {
Password string `binding:"MaxSize(255)"` Password string `binding:"MaxSize(255)"`
Website string `binding:"MaxSize(50)"` Website string `binding:"MaxSize(50)"`
Location string `binding:"MaxSize(50)"` Location string `binding:"MaxSize(50)"`
MaxRepoCreation int
Active bool Active bool
Admin bool Admin bool
AllowGitHook bool AllowGitHook bool

1
modules/auth/org.go

@ -30,6 +30,7 @@ type UpdateOrgSettingForm struct {
Description string `binding:"MaxSize(255)"` Description string `binding:"MaxSize(255)"`
Website string `binding:"Url;MaxSize(100)"` Website string `binding:"Url;MaxSize(100)"`
Location string `binding:"MaxSize(50)"` Location string `binding:"MaxSize(50)"`
MaxRepoCreation int
} }
func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {

5
modules/auth/repo_form.go

@ -69,9 +69,6 @@ func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) {
} }
if len(f.AuthUsername)+len(f.AuthPassword) > 0 { if len(f.AuthUsername)+len(f.AuthPassword) > 0 {
u.User = url.UserPassword(f.AuthUsername, f.AuthPassword) u.User = url.UserPassword(f.AuthUsername, f.AuthPassword)
} else {
// Fake user name and password to prevent prompt and fail quick.
u.User = url.UserPassword("fake_user", "")
} }
remoteAddr = u.String() remoteAddr = u.String()
} else if !user.CanImportLocal() { } else if !user.CanImportLocal() {
@ -94,6 +91,8 @@ type RepoSettingForm struct {
// Advanced settings // Advanced settings
EnableWiki bool EnableWiki bool
EnableExternalWiki bool
ExternalWikiURL string
EnableIssues bool EnableIssues bool
EnableExternalTracker bool EnableExternalTracker bool
TrackerURLFormat string TrackerURLFormat string

4
modules/auth/user_form.go

@ -87,12 +87,12 @@ func (f *SignInForm) Validate(ctx *macaron.Context, errs binding.Errors) binding
// \/ \/ \/ \/ \/ // \/ \/ \/ \/ \/
type UpdateProfileForm struct { type UpdateProfileForm struct {
Name string `binding:"Required;MaxSize(35)"` Name string `binding:"OmitEmpty;MaxSize(35)"`
FullName string `binding:"MaxSize(100)"` FullName string `binding:"MaxSize(100)"`
Email string `binding:"Required;Email;MaxSize(254)"` Email string `binding:"Required;Email;MaxSize(254)"`
Website string `binding:"Url;MaxSize(100)"` Website string `binding:"Url;MaxSize(100)"`
Location string `binding:"MaxSize(50)"` Location string `binding:"MaxSize(50)"`
Gravatar string `binding:"Required;Email;MaxSize(254)"` Gravatar string `binding:"OmitEmpty;Email;MaxSize(254)"`
} }
func (f *UpdateProfileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { func (f *UpdateProfileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {

6
modules/base/markdown.go

@ -133,7 +133,7 @@ var (
MentionPattern = regexp.MustCompile(`(\s|^)@[0-9a-zA-Z_\.]+`) MentionPattern = regexp.MustCompile(`(\s|^)@[0-9a-zA-Z_\.]+`)
commitPattern = regexp.MustCompile(`(\s|^)https?.*commit/[0-9a-zA-Z]+(#+[0-9a-zA-Z-]*)?`) commitPattern = regexp.MustCompile(`(\s|^)https?.*commit/[0-9a-zA-Z]+(#+[0-9a-zA-Z-]*)?`)
issueFullPattern = regexp.MustCompile(`(\s|^)https?.*issues/[0-9]+(#+[0-9a-zA-Z-]*)?`) issueFullPattern = regexp.MustCompile(`(\s|^)https?.*issues/[0-9]+(#+[0-9a-zA-Z-]*)?`)
issueIndexPattern = regexp.MustCompile(`( |^)#[0-9]+\b`) issueIndexPattern = regexp.MustCompile(`( |^|\()#[0-9]+\b`)
sha1CurrentPattern = regexp.MustCompile(`\b[0-9a-f]{40}\b`) sha1CurrentPattern = regexp.MustCompile(`\b[0-9a-f]{40}\b`)
) )
@ -156,8 +156,8 @@ func RenderIssueIndexPattern(rawBytes []byte, urlPrefix string, metas map[string
for _, m := range ms { for _, m := range ms {
var space string var space string
m2 := m m2 := m
if m2[0] == ' ' { if m2[0] != '#' {
space = " " space = string(m2[0])
m2 = m2[1:] m2 = m2[1:]
} }
if metas == nil { if metas == nil {

13
modules/base/tool.go

@ -22,8 +22,7 @@ import (
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/Unknwon/i18n" "github.com/Unknwon/i18n"
"github.com/microcosm-cc/bluemonday" "github.com/microcosm-cc/bluemonday"
"golang.org/x/net/html/charset"
"github.com/gogits/chardet"
"github.com/gogits/gogs/modules/avatar" "github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
@ -52,13 +51,9 @@ func ShortSha(sha1 string) string {
return sha1 return sha1
} }
func DetectEncoding(content []byte) (string, error) { func DetectEncoding(content []byte) string {
detector := chardet.NewTextDetector() _, name, _ := charset.DetermineEncoding(content, setting.Repository.AnsiCharset)
result, err := detector.DetectBest(content) return name
if result.Charset != "UTF-8" && len(setting.Repository.AnsiCharset) > 0 {
return setting.Repository.AnsiCharset, err
}
return result.Charset, err
} }
func BasicAuthDecode(encoded string) (string, string, error) { func BasicAuthDecode(encoded string) (string, string, error) {

1125
modules/bindata/bindata.go

File diff suppressed because one or more lines are too long

26
modules/git/blob.go

@ -1,26 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"bytes"
"errors"
"io"
"github.com/Unknwon/com"
)
type Blob struct {
repo *Repository
*TreeEntry
}
func (b *Blob) Data() (io.Reader, error) {
stdout, stderr, err := com.ExecCmdDirBytes(b.repo.Path, "git", "show", b.ID.String())
if err != nil {
return nil, errors.New(string(stderr))
}
return bytes.NewBuffer(stdout), nil
}

162
modules/git/commit.go

@ -1,162 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"bufio"
"container/list"
"net/http"
"strings"
)
// Commit represents a git commit.
type Commit struct {
Tree
ID sha1 // The id of this commit object
Author *Signature
Committer *Signature
CommitMessage string
parents []sha1 // sha1 strings
submodules map[string]*SubModule
}
// Return the commit message. Same as retrieving CommitMessage directly.
func (c *Commit) Message() string {
return c.CommitMessage
}
func (c *Commit) Summary() string {
return strings.Split(c.CommitMessage, "\n")[0]
}
// Return oid of the parent number n (0-based index). Return nil if no such parent exists.
func (c *Commit) ParentId(n int) (id sha1, err error) {
if n >= len(c.parents) {
err = IDNotExist
return
}
return c.parents[n], nil
}
// Return parent number n (0-based index)
func (c *Commit) Parent(n int) (*Commit, error) {
id, err := c.ParentId(n)
if err != nil {
return nil, err
}
parent, err := c.repo.getCommit(id)
if err != nil {
return nil, err
}
return parent, nil
}
// Return the number of parents of the commit. 0 if this is the
// root commit, otherwise 1,2,...
func (c *Commit) ParentCount() int {
return len(c.parents)
}
func (c *Commit) CommitsBefore() (*list.List, error) {
return c.repo.getCommitsBefore(c.ID)
}
func (c *Commit) CommitsBeforeUntil(commitId string) (*list.List, error) {
ec, err := c.repo.GetCommit(commitId)
if err != nil {
return nil, err
}
return c.repo.CommitsBetween(c, ec)
}
func (c *Commit) CommitsCount() (int, error) {
return c.repo.commitsCount(c.ID)
}
func (c *Commit) SearchCommits(keyword string) (*list.List, error) {
return c.repo.searchCommits(c.ID, keyword)
}
func (c *Commit) CommitsByRange(page int) (*list.List, error) {
return c.repo.commitsByRange(c.ID, page)
}
func (c *Commit) GetCommitOfRelPath(relPath string) (*Commit, error) {
return c.repo.getCommitOfRelPath(c.ID, relPath)
}
func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
modules, err := c.GetSubModules()
if err != nil {
return nil, err
}
return modules[entryname], nil
}
func (c *Commit) GetSubModules() (map[string]*SubModule, error) {
if c.submodules != nil {
return c.submodules, nil
}
entry, err := c.GetTreeEntryByPath(".gitmodules")
if err != nil {
return nil, err
}
rd, err := entry.Blob().Data()
if err != nil {
return nil, err
}
scanner := bufio.NewScanner(rd)
c.submodules = make(map[string]*SubModule)
var ismodule bool
var path string
for scanner.Scan() {
if strings.HasPrefix(scanner.Text(), "[submodule") {
ismodule = true
continue
}
if ismodule {
fields := strings.Split(scanner.Text(), "=")
k := strings.TrimSpace(fields[0])
if k == "path" {
path = strings.TrimSpace(fields[1])
} else if k == "url" {
c.submodules[path] = &SubModule{path, strings.TrimSpace(fields[1])}
ismodule = false
}
}
}
return c.submodules, nil
}
func isImageFile(data []byte) (string, bool) {
contentType := http.DetectContentType(data)
if strings.Index(contentType, "image/") != -1 {
return contentType, true
}
return contentType, false
}
func (c *Commit) IsImageFile(name string) bool {
blob, err := c.GetBlobByPath(name)
if err != nil {
return false
}
dataRc, err := blob.Data()
if err != nil {
return false
}
buf := make([]byte, 1024)
n, _ := dataRc.Read(buf)
if n > 0 {
buf = buf[:n]
}
_, isImage := isImageFile(buf)
return isImage
}

36
modules/git/commit_archive.go

@ -1,36 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"fmt"
"github.com/Unknwon/com"
)
type ArchiveType int
const (
ZIP ArchiveType = iota + 1
TARGZ
)
func (c *Commit) CreateArchive(path string, archiveType ArchiveType) error {
var format string
switch archiveType {
case ZIP:
format = "zip"
case TARGZ:
format = "tar.gz"
default:
return fmt.Errorf("unknown format: %v", archiveType)
}
_, stderr, err := com.ExecCmdDir(c.repo.Path, "git", "archive", "--format="+format, "-o", path, c.ID.String())
if err != nil {
return fmt.Errorf("%s", stderr)
}
return nil
}

22
modules/git/error.go

@ -1,22 +0,0 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"fmt"
)
type ErrUnsupportedVersion struct {
Required string
}
func IsErrUnsupportedVersion(err error) bool {
_, ok := err.(ErrUnsupportedVersion)
return ok
}
func (err ErrUnsupportedVersion) Error() string {
return fmt.Sprintf("Operation requires higher version [required: %s]", err.Required)
}

125
modules/git/hooks.go

@ -1,125 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"errors"
"io/ioutil"
"os"
"path"
"strings"
"github.com/Unknwon/com"
)
// hookNames is a list of Git hooks' name that are supported.
var hookNames = []string{
"applypatch-msg",
"pre-applypatch",
"post-applypatch",
"pre-commit",
"prepare-commit-msg",
"commit-msg",
"post-commit",
"pre-rebase",
"post-checkout",
"post-merge",
"pre-push",
"pre-receive",
// "update",
"post-receive",
"post-update",
"push-to-checkout",
"pre-auto-gc",
"post-rewrite",
}
var (
ErrNotValidHook = errors.New("not a valid Git hook")
)
// IsValidHookName returns true if given name is a valid Git hook.
func IsValidHookName(name string) bool {
for _, hn := range hookNames {
if hn == name {
return true
}
}
return false
}
// Hook represents a Git hook.
type Hook struct {
name string
IsActive bool // Indicates whether repository has this hook.
Content string // Content of hook if it's active.
Sample string // Sample content from Git.
path string // Hook file path.
}
// GetHook returns a Git hook by given name and repository.
func GetHook(repoPath, name string) (*Hook, error) {
if !IsValidHookName(name) {
return nil, ErrNotValidHook
}
h := &Hook{
name: name,
path: path.Join(repoPath, "hooks", name),
}
if isFile(h.path) {
data, err := ioutil.ReadFile(h.path)
if err != nil {
return nil, err
}
h.IsActive = true
h.Content = string(data)
} else if isFile(h.path + ".sample") {
data, err := ioutil.ReadFile(h.path + ".sample")
if err != nil {
return nil, err
}
h.Sample = string(data)
}
return h, nil
}
func (h *Hook) Name() string {
return h.name
}
// Update updates hook settings.
func (h *Hook) Update() error {
if len(strings.TrimSpace(h.Content)) == 0 {
if com.IsExist(h.path) {
return os.Remove(h.path)
}
return nil
}
return ioutil.WriteFile(h.path, []byte(strings.Replace(h.Content, "\r", "", -1)), os.ModePerm)
}
// ListHooks returns a list of Git hooks of given repository.
func ListHooks(repoPath string) (_ []*Hook, err error) {
if !isDir(path.Join(repoPath, "hooks")) {
return nil, errors.New("hooks path does not exist")
}
hooks := make([]*Hook, len(hookNames))
for i, name := range hookNames {
hooks[i], err = GetHook(repoPath, name)
if err != nil {
return nil, err
}
}
return hooks, nil
}
func (repo *Repository) GetHook(name string) (*Hook, error) {
return GetHook(repo.Path, name)
}
func (repo *Repository) Hooks() ([]*Hook, error) {
return ListHooks(repo.Path)
}

30
modules/git/repo.go

@ -1,30 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"errors"
"path/filepath"
)
// Repository represents a Git repository.
type Repository struct {
Path string
commitCache map[sha1]*Commit
tagCache map[sha1]*Tag
}
// OpenRepository opens the repository at the given path.
func OpenRepository(repoPath string) (*Repository, error) {
repoPath, err := filepath.Abs(repoPath)
if err != nil {
return nil, err
} else if !isDir(repoPath) {
return nil, errors.New("no such file or directory")
}
return &Repository{Path: repoPath}, nil
}

50
modules/git/repo_branch.go

@ -1,50 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"strings"
"github.com/Unknwon/com"
)
func IsBranchExist(repoPath, branchName string) bool {
_, _, err := com.ExecCmdDir(repoPath, "git", "show-ref", "--verify", "refs/heads/"+branchName)
return err == nil
}
func (repo *Repository) IsBranchExist(branchName string) bool {
return IsBranchExist(repo.Path, branchName)
}
func (repo *Repository) GetBranches() ([]string, error) {
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--heads")
if err != nil {
return nil, concatenateError(err, stderr)
}
infos := strings.Split(stdout, "\n")
branches := make([]string, len(infos)-1)
for i, info := range infos[:len(infos)-1] {
parts := strings.Split(info, " ")
if len(parts) != 2 {
continue // NOTE: I should believe git will not give me wrong string.
}
branches[i] = strings.TrimPrefix(parts[1], "refs/heads/")
}
return branches, nil
}
// SetDefaultBranch sets default branch of repository.
func (repo *Repository) SetDefaultBranch(branchName string) error {
if gitVer.LessThan(MustParseVersion("1.7.10")) {
return ErrUnsupportedVersion{"1.7.10"}
}
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "symbolic-ref", "HEAD", "refs/heads/"+branchName)
if err != nil {
return concatenateError(err, stderr)
}
return nil
}

341
modules/git/repo_commit.go

@ -1,341 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"bytes"
"container/list"
"errors"
"fmt"
"strings"
"sync"
"github.com/Unknwon/com"
)
func (repo *Repository) getCommitIdOfRef(refpath string) (string, error) {
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--verify", refpath)
if err != nil {
return "", errors.New(stderr)
}
return strings.Split(stdout, " ")[0], nil
}
func (repo *Repository) GetCommitIdOfBranch(branchName string) (string, error) {
return repo.getCommitIdOfRef("refs/heads/" + branchName)
}
// get branch's last commit or a special commit by id string
func (repo *Repository) GetCommitOfBranch(branchName string) (*Commit, error) {
commitId, err := repo.GetCommitIdOfBranch(branchName)
if err != nil {
return nil, err
}
return repo.GetCommit(commitId)
}
func (repo *Repository) GetCommitIdOfTag(tagName string) (string, error) {
return repo.getCommitIdOfRef("refs/tags/" + tagName)
}
func (repo *Repository) GetCommitOfTag(tagName string) (*Commit, error) {
tag, err := repo.GetTag(tagName)
if err != nil {
return nil, err
}
return tag.Commit()
}
// Parse commit information from the (uncompressed) raw
// data from the commit object.
// \n\n separate headers from message
func parseCommitData(data []byte) (*Commit, error) {
commit := new(Commit)
commit.parents = make([]sha1, 0, 1)
// we now have the contents of the commit object. Let's investigate...
nextline := 0
l:
for {
eol := bytes.IndexByte(data[nextline:], '\n')
switch {
case eol > 0:
line := data[nextline : nextline+eol]
spacepos := bytes.IndexByte(line, ' ')
reftype := line[:spacepos]
switch string(reftype) {
case "tree":
id, err := NewIdFromString(string(line[spacepos+1:]))
if err != nil {
return nil, err
}
commit.Tree.ID = id
case "parent":
// A commit can have one or more parents
oid, err := NewIdFromString(string(line[spacepos+1:]))
if err != nil {
return nil, err
}
commit.parents = append(commit.parents, oid)
case "author":
sig, err := newSignatureFromCommitline(line[spacepos+1:])
if err != nil {
return nil, err
}
commit.Author = sig
case "committer":
sig, err := newSignatureFromCommitline(line[spacepos+1:])
if err != nil {
return nil, err
}
commit.Committer = sig
}
nextline += eol + 1
case eol == 0:
commit.CommitMessage = string(data[nextline+1:])
break l
default:
break l
}
}
return commit, nil
}
func (repo *Repository) getCommit(id sha1) (*Commit, error) {
if repo.commitCache != nil {
if c, ok := repo.commitCache[id]; ok {
return c, nil
}
} else {
repo.commitCache = make(map[sha1]*Commit, 10)
}
data, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "cat-file", "-p", id.String())
if err != nil {
return nil, concatenateError(err, string(stderr))
}
commit, err := parseCommitData(data)
if err != nil {
return nil, err
}
commit.repo = repo
commit.ID = id
repo.commitCache[id] = commit
return commit, nil
}
// Find the commit object in the repository.
func (repo *Repository) GetCommit(commitId string) (*Commit, error) {
id, err := NewIdFromString(commitId)
if err != nil {
return nil, err
}
return repo.getCommit(id)
}
func (repo *Repository) commitsCount(id sha1) (int, error) {
if gitVer.LessThan(MustParseVersion("1.8.0")) {
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log",
"--pretty=format:''", id.String())
if err != nil {
return 0, errors.New(string(stderr))
}
return len(bytes.Split(stdout, []byte("\n"))), nil
}
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count", id.String())
if err != nil {
return 0, errors.New(stderr)
}
return com.StrTo(strings.TrimSpace(stdout)).Int()
}
func (repo *Repository) CommitsCount(commitId string) (int, error) {
id, err := NewIdFromString(commitId)
if err != nil {
return 0, err
}
return repo.commitsCount(id)
}
func (repo *Repository) commitsCountBetween(start, end sha1) (int, error) {
if gitVer.LessThan(MustParseVersion("1.8.0")) {
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log",
"--pretty=format:''", start.String()+"..."+end.String())
if err != nil {
return 0, errors.New(string(stderr))
}
return len(bytes.Split(stdout, []byte("\n"))), nil
}
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count",
start.String()+"..."+end.String())
if err != nil {
return 0, errors.New(stderr)
}
return com.StrTo(strings.TrimSpace(stdout)).Int()
}
func (repo *Repository) CommitsCountBetween(startCommitID, endCommitID string) (int, error) {
start, err := NewIdFromString(startCommitID)
if err != nil {
return 0, err
}
end, err := NewIdFromString(endCommitID)
if err != nil {
return 0, err
}
return repo.commitsCountBetween(start, end)
}
func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (int, error) {
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "diff", "--name-only",
startCommitID+"..."+endCommitID)
if err != nil {
return 0, fmt.Errorf("list changed files: %v", concatenateError(err, stderr))
}
return len(strings.Split(stdout, "\n")) - 1, nil
}
// used only for single tree, (]
func (repo *Repository) CommitsBetween(last *Commit, before *Commit) (*list.List, error) {
l := list.New()
if last == nil || last.ParentCount() == 0 {
return l, nil
}
var err error
cur := last
for {
if cur.ID.Equal(before.ID) {
break
}
l.PushBack(cur)
if cur.ParentCount() == 0 {
break
}
cur, err = cur.Parent(0)
if err != nil {
return nil, err
}
}
return l, nil
}
func (repo *Repository) commitsBefore(lock *sync.Mutex, l *list.List, parent *list.Element, id sha1, limit int) error {
commit, err := repo.getCommit(id)
if err != nil {
return fmt.Errorf("getCommit: %v", err)
}
var e *list.Element
if parent == nil {
e = l.PushBack(commit)
} else {
var in = parent
for {
if in == nil {
break
} else if in.Value.(*Commit).ID.Equal(commit.ID) {
return nil
} else {
if in.Next() == nil {
break
}
if in.Value.(*Commit).Committer.When.Equal(commit.Committer.When) {
break
}
if in.Value.(*Commit).Committer.When.After(commit.Committer.When) &&
in.Next().Value.(*Commit).Committer.When.Before(commit.Committer.When) {
break
}
}
in = in.Next()
}
e = l.InsertAfter(commit, in)
}
var pr = parent
if commit.ParentCount() > 1 {
pr = e
}
for i := 0; i < commit.ParentCount(); i++ {
id, err := commit.ParentId(i)
if err != nil {
return err
}
err = repo.commitsBefore(lock, l, pr, id, 0)
if err != nil {
return err
}
}
return nil
}
func (repo *Repository) FileCommitsCount(branch, file string) (int, error) {
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count",
branch, "--", file)
if err != nil {
return 0, errors.New(stderr)
}
return com.StrTo(strings.TrimSpace(stdout)).Int()
}
func (repo *Repository) CommitsByFileAndRange(branch, file string, page int) (*list.List, error) {
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", branch,
"--skip="+com.ToStr((page-1)*50), "--max-count=50", prettyLogFormat, "--", file)
if err != nil {
return nil, errors.New(string(stderr))
}
return parsePrettyFormatLog(repo, stdout)
}
func (repo *Repository) getCommitsBefore(id sha1) (*list.List, error) {
l := list.New()
lock := new(sync.Mutex)
return l, repo.commitsBefore(lock, l, nil, id, 0)
}
func (repo *Repository) searchCommits(id sha1, keyword string) (*list.List, error) {
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(), "-100",
"-i", "--grep="+keyword, prettyLogFormat)
if err != nil {
return nil, err
} else if len(stderr) > 0 {
return nil, errors.New(string(stderr))
}
return parsePrettyFormatLog(repo, stdout)
}
var CommitsRangeSize = 50
func (repo *Repository) commitsByRange(id sha1, page int) (*list.List, error) {
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(),
"--skip="+com.ToStr((page-1)*CommitsRangeSize), "--max-count="+com.ToStr(CommitsRangeSize), prettyLogFormat)
if err != nil {
return nil, errors.New(string(stderr))
}
return parsePrettyFormatLog(repo, stdout)
}
func (repo *Repository) getCommitOfRelPath(id sha1, relPath string) (*Commit, error) {
stdout, _, err := com.ExecCmdDir(repo.Path, "git", "log", "-1", prettyLogFormat, id.String(), "--", relPath)
if err != nil {
return nil, err
}
id, err = NewIdFromString(string(stdout))
if err != nil {
return nil, err
}
return repo.getCommit(id)
}

14
modules/git/repo_object.go

@ -1,14 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
type ObjectType string
const (
COMMIT ObjectType = "commit"
TREE ObjectType = "tree"
BLOB ObjectType = "blob"
TAG ObjectType = "tag"
)

104
modules/git/repo_pull.go

@ -1,104 +0,0 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"container/list"
"fmt"
"strings"
"time"
"github.com/Unknwon/com"
)
type PullRequestInfo struct {
MergeBase string
Commits *list.List
// Diff *Diff
NumFiles int
}
// GetMergeBase checks and returns merge base of two branches.
func (repo *Repository) GetMergeBase(remoteBranch, headBranch string) (string, error) {
// Get merge base commit.
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "merge-base", remoteBranch, headBranch)
if err != nil {
return "", fmt.Errorf("get merge base: %v", concatenateError(err, stderr))
}
return strings.TrimSpace(stdout), nil
}
// AddRemote adds a remote to repository.
func (repo *Repository) AddRemote(name, path string) error {
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "add", "-f", name, path)
if err != nil {
return fmt.Errorf("add remote(%s - %s): %v", name, path, concatenateError(err, stderr))
}
return nil
}
// RemoveRemote removes a remote from repository.
func (repo *Repository) RemoveRemote(name string) error {
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "remove", name)
if err != nil {
return fmt.Errorf("remove remote(%s): %v", name, concatenateError(err, stderr))
}
return nil
}
// GetPullRequestInfo generates and returns pull request information
// between base and head branches of repositories.
func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch string) (_ *PullRequestInfo, err error) {
// Add a temporary remote.
tmpRemote := com.ToStr(time.Now().UnixNano())
if err = repo.AddRemote(tmpRemote, basePath); err != nil {
return nil, fmt.Errorf("AddRemote: %v", err)
}
defer func() {
repo.RemoveRemote(tmpRemote)
}()
remoteBranch := "remotes/" + tmpRemote + "/" + baseBranch
prInfo := new(PullRequestInfo)
prInfo.MergeBase, err = repo.GetMergeBase(remoteBranch, headBranch)
if err != nil {
return nil, fmt.Errorf("GetMergeBase: %v", err)
}
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "log", prInfo.MergeBase+"..."+headBranch, prettyLogFormat)
if err != nil {
return nil, fmt.Errorf("list diff logs: %v", concatenateError(err, stderr))
}
prInfo.Commits, err = parsePrettyFormatLog(repo, []byte(stdout))
if err != nil {
return nil, fmt.Errorf("parsePrettyFormatLog: %v", err)
}
// Count number of changed files.
stdout, stderr, err = com.ExecCmdDir(repo.Path, "git", "diff", "--name-only", remoteBranch+"..."+headBranch)
if err != nil {
return nil, fmt.Errorf("list changed files: %v", concatenateError(err, stderr))
}
prInfo.NumFiles = len(strings.Split(stdout, "\n")) - 1
return prInfo, nil
}
// GetPatch generates and returns patch data between given branches.
func (repo *Repository) GetPatch(mergeBase, headBranch string) ([]byte, error) {
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "diff", "-p", "--binary", mergeBase, headBranch)
if err != nil {
return nil, concatenateError(err, string(stderr))
}
return stdout, nil
}
// Merge merges pull request from head repository and branch.
func (repo *Repository) Merge(headRepoPath string, baseBranch, headBranch string) error {
return nil
}

117
modules/git/repo_tag.go

@ -1,117 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"errors"
"strings"
"github.com/Unknwon/com"
)
func IsTagExist(repoPath, tagName string) bool {
_, _, err := com.ExecCmdDir(repoPath, "git", "show-ref", "--verify", "refs/tags/"+tagName)
return err == nil
}
func (repo *Repository) IsTagExist(tagName string) bool {
return IsTagExist(repo.Path, tagName)
}
func (repo *Repository) getTagsReversed() ([]string, error) {
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l", "--sort=-v:refname")
if err != nil {
return nil, concatenateError(err, stderr)
}
tags := strings.Split(stdout, "\n")
return tags[:len(tags)-1], nil
}
// GetTags returns all tags of given repository.
func (repo *Repository) GetTags() ([]string, error) {
if gitVer.AtLeast(MustParseVersion("2.0.0")) {
return repo.getTagsReversed()
}
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l")
if err != nil {
return nil, concatenateError(err, stderr)
}
tags := strings.Split(stdout, "\n")
return tags[:len(tags)-1], nil
}
func (repo *Repository) CreateTag(tagName, idStr string) error {
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", tagName, idStr)
if err != nil {
return errors.New(stderr)
}
return nil
}
func (repo *Repository) getTag(id sha1) (*Tag, error) {
if repo.tagCache != nil {
if t, ok := repo.tagCache[id]; ok {
return t, nil
}
} else {
repo.tagCache = make(map[sha1]*Tag, 10)
}
// Get tag type.
tp, stderr, err := com.ExecCmdDir(repo.Path, "git", "cat-file", "-t", id.String())
if err != nil {
return nil, errors.New(stderr)
}
tp = strings.TrimSpace(tp)
// Tag is a commit.
if ObjectType(tp) == COMMIT {
tag := &Tag{
ID: id,
Object: id,
Type: string(COMMIT),
repo: repo,
}
repo.tagCache[id] = tag
return tag, nil
}
// Tag with message.
data, bytErr, err := com.ExecCmdDirBytes(repo.Path, "git", "cat-file", "-p", id.String())
if err != nil {
return nil, errors.New(string(bytErr))
}
tag, err := parseTagData(data)
if err != nil {
return nil, err
}
tag.ID = id
tag.repo = repo
repo.tagCache[id] = tag
return tag, nil
}
// GetTag returns a Git tag by given name.
func (repo *Repository) GetTag(tagName string) (*Tag, error) {
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--tags", tagName)
if err != nil {
return nil, errors.New(stderr)
}
id, err := NewIdFromString(strings.Split(stdout, " ")[0])
if err != nil {
return nil, err
}
tag, err := repo.getTag(id)
if err != nil {
return nil, err
}
tag.Name = tagName
return tag, nil
}

32
modules/git/repo_tree.go

@ -1,32 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"fmt"
"github.com/Unknwon/com"
)
// Find the tree object in the repository.
func (repo *Repository) GetTree(idStr string) (*Tree, error) {
id, err := NewIdFromString(idStr)
if err != nil {
return nil, err
}
return repo.getTree(id)
}
func (repo *Repository) getTree(id sha1) (*Tree, error) {
treePath := filepathFromSHA1(repo.Path, id.String())
if !com.IsFile(treePath) {
_, _, err := com.ExecCmdDir(repo.Path, "git", "ls-tree", id.String())
if err != nil {
return nil, fmt.Errorf("repo.getTree: %v", ErrNotExist)
}
}
return NewTree(repo, id), nil
}

87
modules/git/sha1.go

@ -1,87 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"encoding/hex"
"errors"
"fmt"
"strings"
)
var (
IDNotExist = errors.New("sha1 ID does not exist")
)
type sha1 [20]byte
// Return true if s has the same sha1 as caller.
// Support 40-length-string, []byte, sha1
func (id sha1) Equal(s2 interface{}) bool {
switch v := s2.(type) {
case string:
if len(v) != 40 {
return false
}
return v == id.String()
case []byte:
if len(v) != 20 {
return false
}
for i, v := range v {
if id[i] != v {
return false
}
}
case sha1:
for i, v := range v {
if id[i] != v {
return false
}
}
default:
return false
}
return true
}
// Return string (hex) representation of the Oid
func (s sha1) String() string {
result := make([]byte, 0, 40)
hexvalues := []byte("0123456789abcdef")
for i := 0; i < 20; i++ {
result = append(result, hexvalues[s[i]>>4])
result = append(result, hexvalues[s[i]&0xf])
}
return string(result)
}
// Create a new sha1 from a 20 byte slice.
func NewId(b []byte) (sha1, error) {
var id sha1
if len(b) != 20 {
return id, errors.New("Length must be 20")
}
for i := 0; i < 20; i++ {
id[i] = b[i]
}
return id, nil
}
// Create a new sha1 from a Sha1 string of length 40.
func NewIdFromString(s string) (sha1, error) {
s = strings.TrimSpace(s)
var id sha1
if len(s) != 40 {
return id, fmt.Errorf("Length must be 40")
}
b, err := hex.DecodeString(s)
if err != nil {
return id, err
}
return NewId(b)
}

51
modules/git/signature.go

@ -1,51 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"bytes"
"strconv"
"time"
)
// Author and Committer information
type Signature struct {
Email string
Name string
When time.Time
}
// Helper to get a signature from the commit line, which looks like these:
// author Patrick Gundlach <gundlach@speedata.de> 1378823654 +0200
// author Patrick Gundlach <gundlach@speedata.de> Thu, 07 Apr 2005 22:13:13 +0200
// but without the "author " at the beginning (this method should)
// be used for author and committer.
//
// FIXME: include timezone for timestamp!
func newSignatureFromCommitline(line []byte) (_ *Signature, err error) {
sig := new(Signature)
emailStart := bytes.IndexByte(line, '<')
sig.Name = string(line[:emailStart-1])
emailEnd := bytes.IndexByte(line, '>')
sig.Email = string(line[emailStart+1 : emailEnd])
// Check date format.
firstChar := line[emailEnd+2]
if firstChar >= 48 && firstChar <= 57 {
timestop := bytes.IndexByte(line[emailEnd+2:], ' ')
timestring := string(line[emailEnd+2 : emailEnd+2+timestop])
seconds, err := strconv.ParseInt(timestring, 10, 64)
if err != nil {
return nil, err
}
sig.When = time.Unix(seconds, 0)
} else {
sig.When, err = time.Parse("Mon Jan _2 15:04:05 2006 -0700", string(line[emailEnd+2:]))
if err != nil {
return nil, err
}
}
return sig, nil
}

20
modules/git/signature_test.go

@ -1,20 +0,0 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func Test_newSignatureFromCommitline(t *testing.T) {
Convey("Parse signature from commit line", t, func() {
line := "Intern <intern@macbook-intern.(none)> 1445412825 +0200"
sig, err := newSignatureFromCommitline([]byte(line))
So(err, ShouldBeNil)
So(sig, ShouldNotBeNil)
})
}

70
modules/git/submodule.go

@ -1,70 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"strings"
"github.com/gogits/gogs/modules/setting"
)
type SubModule struct {
Name string
Url string
}
// SubModuleFile represents a file with submodule type.
type SubModuleFile struct {
*Commit
refUrl string
refId string
}
func NewSubModuleFile(c *Commit, refUrl, refId string) *SubModuleFile {
return &SubModuleFile{
Commit: c,
refUrl: refUrl,
refId: refId,
}
}
// RefUrl guesses and returns reference URL.
func (sf *SubModuleFile) RefUrl() string {
if sf.refUrl == "" {
return ""
}
url := strings.TrimSuffix(sf.refUrl, ".git")
// git://xxx/user/repo
if strings.HasPrefix(url, "git://") {
return "http://" + strings.TrimPrefix(url, "git://")
}
// http[s]://xxx/user/repo
if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
return url
}
// sysuser@xxx:user/repo
i := strings.Index(url, "@")
j := strings.LastIndex(url, ":")
if i > -1 && j > -1 {
// fix problem with reverse proxy works only with local server
if strings.Contains(setting.AppUrl, url[i+1:j]) {
return setting.AppUrl + url[j+1:]
} else {
return "http://" + url[i+1:j] + "/" + url[j+1:]
}
}
return url
}
// RefId returns reference ID.
func (sf *SubModuleFile) RefId() string {
return sf.refId
}

67
modules/git/tag.go

@ -1,67 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"bytes"
)
// Tag represents a Git tag.
type Tag struct {
Name string
ID sha1
repo *Repository
Object sha1 // The id of this commit object
Type string
Tagger *Signature
TagMessage string
}
func (tag *Tag) Commit() (*Commit, error) {
return tag.repo.getCommit(tag.Object)
}
// Parse commit information from the (uncompressed) raw
// data from the commit object.
// \n\n separate headers from message
func parseTagData(data []byte) (*Tag, error) {
tag := new(Tag)
// we now have the contents of the commit object. Let's investigate...
nextline := 0
l:
for {
eol := bytes.IndexByte(data[nextline:], '\n')
switch {
case eol > 0:
line := data[nextline : nextline+eol]
spacepos := bytes.IndexByte(line, ' ')
reftype := line[:spacepos]
switch string(reftype) {
case "object":
id, err := NewIdFromString(string(line[spacepos+1:]))
if err != nil {
return nil, err
}
tag.Object = id
case "type":
// A commit can have one or more parents
tag.Type = string(line[spacepos+1:])
case "tagger":
sig, err := newSignatureFromCommitline(line[spacepos+1:])
if err != nil {
return nil, err
}
tag.Tagger = sig
}
nextline += eol + 1
case eol == 0:
tag.TagMessage = string(data[nextline+1:])
break l
default:
break l
}
}
return tag, nil
}

157
modules/git/tree.go

@ -1,157 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"bytes"
"errors"
"strings"
"github.com/Unknwon/com"
)
var (
ErrNotExist = errors.New("error not exist")
)
// A tree is a flat directory listing.
type Tree struct {
ID sha1
repo *Repository
// parent tree
ptree *Tree
entries Entries
entriesParsed bool
}
var escapeChar = []byte("\\")
func UnescapeChars(in []byte) []byte {
if bytes.Index(in, escapeChar) == -1 {
return in
}
endIdx := len(in) - 1
isEscape := false
out := make([]byte, 0, endIdx+1)
for i := range in {
if in[i] == '\\' && !isEscape {
isEscape = true
continue
}
isEscape = false
out = append(out, in[i])
}
return out
}
// Parse tree information from the (uncompressed) raw
// data from the tree object.
func parseTreeData(tree *Tree, data []byte) ([]*TreeEntry, error) {
entries := make([]*TreeEntry, 0, 10)
l := len(data)
pos := 0
for pos < l {
entry := new(TreeEntry)
entry.ptree = tree
step := 6
switch string(data[pos : pos+step]) {
case "100644":
entry.mode = ModeBlob
entry.Type = BLOB
case "100755":
entry.mode = ModeExec
entry.Type = BLOB
case "120000":
entry.mode = ModeSymlink
entry.Type = BLOB
case "160000":
entry.mode = ModeCommit
entry.Type = COMMIT
step = 8
case "040000":
entry.mode = ModeTree
entry.Type = TREE
default:
return nil, errors.New("unknown type: " + string(data[pos:pos+step]))
}
pos += step + 6 // Skip string type of entry type.
step = 40
id, err := NewIdFromString(string(data[pos : pos+step]))
if err != nil {
return nil, err
}
entry.ID = id
pos += step + 1 // Skip half of sha1.
step = bytes.IndexByte(data[pos:], '\n')
// In case entry name is surrounded by double quotes(it happens only in git-shell).
if data[pos] == '"' {
entry.name = string(UnescapeChars(data[pos+1 : pos+step-1]))
} else {
entry.name = string(data[pos : pos+step])
}
pos += step + 1
entries = append(entries, entry)
}
return entries, nil
}
func (t *Tree) SubTree(rpath string) (*Tree, error) {
if len(rpath) == 0 {
return t, nil
}
paths := strings.Split(rpath, "/")
var err error
var g = t
var p = t
var te *TreeEntry
for _, name := range paths {
te, err = p.GetTreeEntryByPath(name)
if err != nil {
return nil, err
}
g, err = t.repo.getTree(te.ID)
if err != nil {
return nil, err
}
g.ptree = p
p = g
}
return g, nil
}
func (t *Tree) ListEntries(relpath string) (Entries, error) {
if t.entriesParsed {
return t.entries, nil
}
t.entriesParsed = true
stdout, stderr, err := com.ExecCmdDirBytes(t.repo.Path,
"git", "ls-tree", t.ID.String())
if err != nil {
if strings.Contains(err.Error(), "exit status 128") {
return nil, errors.New(strings.TrimSpace(string(stderr)))
}
return nil, err
}
t.entries, err = parseTreeData(t, stdout)
return t.entries, err
}
func NewTree(repo *Repository, id sha1) *Tree {
tree := new(Tree)
tree.ID = id
tree.repo = repo
return tree
}

59
modules/git/tree_blob.go

@ -1,59 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"fmt"
"path"
"strings"
)
func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) {
if len(relpath) == 0 {
return &TreeEntry{
ID: t.ID,
Type: TREE,
mode: ModeTree,
}, nil
// return nil, fmt.Errorf("GetTreeEntryByPath(empty relpath): %v", ErrNotExist)
}
relpath = path.Clean(relpath)
parts := strings.Split(relpath, "/")
var err error
tree := t
for i, name := range parts {
if i == len(parts)-1 {
entries, err := tree.ListEntries(path.Dir(relpath))
if err != nil {
return nil, err
}
for _, v := range entries {
if v.name == name {
return v, nil
}
}
} else {
tree, err = tree.SubTree(name)
if err != nil {
return nil, err
}
}
}
return nil, fmt.Errorf("GetTreeEntryByPath: %v", ErrNotExist)
}
func (t *Tree) GetBlobByPath(rpath string) (*Blob, error) {
entry, err := t.GetTreeEntryByPath(rpath)
if err != nil {
return nil, err
}
if !entry.IsDir() {
return entry.Blob(), nil
}
return nil, ErrNotExist
}

113
modules/git/tree_entry.go

@ -1,113 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"sort"
"strings"
"github.com/Unknwon/com"
)
type EntryMode int
// There are only a few file modes in Git. They look like unix file modes, but they can only be
// one of these.
const (
ModeBlob EntryMode = 0100644
ModeExec EntryMode = 0100755
ModeSymlink EntryMode = 0120000
ModeCommit EntryMode = 0160000
ModeTree EntryMode = 0040000
)
type TreeEntry struct {
ID sha1
Type ObjectType
mode EntryMode
name string
ptree *Tree
commited bool
size int64
sized bool
}
func (te *TreeEntry) Name() string {
return te.name
}
func (te *TreeEntry) Size() int64 {
if te.IsDir() {
return 0
}
if te.sized {
return te.size
}
stdout, _, err := com.ExecCmdDir(te.ptree.repo.Path, "git", "cat-file", "-s", te.ID.String())
if err != nil {
return 0
}
te.sized = true
te.size = com.StrTo(strings.TrimSpace(stdout)).MustInt64()
return te.size
}
func (te *TreeEntry) IsSubModule() bool {
return te.mode == ModeCommit
}
func (te *TreeEntry) IsDir() bool {
return te.mode == ModeTree
}
func (te *TreeEntry) EntryMode() EntryMode {
return te.mode
}
func (te *TreeEntry) Blob() *Blob {
return &Blob{
repo: te.ptree.repo,
TreeEntry: te,
}
}
type Entries []*TreeEntry
var sorter = []func(t1, t2 *TreeEntry) bool{
func(t1, t2 *TreeEntry) bool {
return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
},
func(t1, t2 *TreeEntry) bool {
return t1.name < t2.name
},
}
func (bs Entries) Len() int { return len(bs) }
func (bs Entries) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] }
func (bs Entries) Less(i, j int) bool {
t1, t2 := bs[i], bs[j]
var k int
for k = 0; k < len(sorter)-1; k++ {
sort := sorter[k]
switch {
case sort(t1, t2):
return true
case sort(t2, t1):
return false
}
}
return sorter[k](t1, t2)
}
func (bs Entries) Sort() {
sort.Sort(bs)
}

82
modules/git/utils.go

@ -1,82 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"bytes"
"container/list"
"fmt"
"os"
"path/filepath"
"strings"
)
const prettyLogFormat = `--pretty=format:%H`
func parsePrettyFormatLog(repo *Repository, logByts []byte) (*list.List, error) {
l := list.New()
if len(logByts) == 0 {
return l, nil
}
parts := bytes.Split(logByts, []byte{'\n'})
for _, commitId := range parts {
commit, err := repo.GetCommit(string(commitId))
if err != nil {
return nil, err
}
l.PushBack(commit)
}
return l, nil
}
func RefEndName(refStr string) string {
if strings.HasPrefix(refStr, "refs/heads/") {
// trim the "refs/heads/"
return refStr[len("refs/heads/"):]
}
index := strings.LastIndex(refStr, "/")
if index != -1 {
return refStr[index+1:]
}
return refStr
}
// If the object is stored in its own file (i.e not in a pack file),
// this function returns the full path to the object file.
// It does not test if the file exists.
func filepathFromSHA1(rootdir, sha1 string) string {
return filepath.Join(rootdir, "objects", sha1[:2], sha1[2:])
}
// isDir returns true if given path is a directory,
// or returns false when it's a file or does not exist.
func isDir(dir string) bool {
f, e := os.Stat(dir)
if e != nil {
return false
}
return f.IsDir()
}
// isFile returns true if given path is a file,
// or returns false when it's a directory or does not exist.
func isFile(filePath string) bool {
f, e := os.Stat(filePath)
if e != nil {
return false
}
return !f.IsDir()
}
func concatenateError(err error, stderr string) error {
if len(stderr) == 0 {
return err
}
return fmt.Errorf("%v: %s", err, stderr)
}

104
modules/git/version.go

@ -1,104 +0,0 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"errors"
"fmt"
"strings"
"github.com/Unknwon/com"
)
var (
// Cached Git version.
gitVer *Version
)
// Version represents version of Git.
type Version struct {
Major, Minor, Patch int
}
func ParseVersion(verStr string) (*Version, error) {
infos := strings.Split(verStr, ".")
if len(infos) < 3 {
return nil, errors.New("incorrect version input")
}
v := &Version{}
for i, s := range infos {
switch i {
case 0:
v.Major, _ = com.StrTo(s).Int()
case 1:
v.Minor, _ = com.StrTo(s).Int()
case 2:
v.Patch, _ = com.StrTo(strings.TrimSpace(s)).Int()
}
}
return v, nil
}
func MustParseVersion(verStr string) *Version {
v, _ := ParseVersion(verStr)
return v
}
// Compare compares two versions,
// it returns 1 if original is greater, -1 if original is smaller, 0 if equal.
func (v *Version) Compare(that *Version) int {
if v.Major > that.Major {
return 1
} else if v.Major < that.Major {
return -1
}
if v.Minor > that.Minor {
return 1
} else if v.Minor < that.Minor {
return -1
}
if v.Patch > that.Patch {
return 1
} else if v.Patch < that.Patch {
return -1
}
return 0
}
func (v *Version) LessThan(that *Version) bool {
return v.Compare(that) < 0
}
func (v *Version) AtLeast(that *Version) bool {
return v.Compare(that) >= 0
}
func (v *Version) String() string {
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
// GetVersion returns current Git version installed.
func GetVersion() (*Version, error) {
if gitVer != nil {
return gitVer, nil
}
stdout, stderr, err := com.ExecCmd("git", "version")
if err != nil {
return nil, errors.New(stderr)
}
infos := strings.Split(stdout, " ")
if len(infos) < 3 {
return nil, errors.New("not enough output")
}
gitVer, err = ParseVersion(infos[2])
return gitVer, err
}

5
modules/middleware/context.go

@ -18,10 +18,11 @@ import (
"github.com/go-macaron/session" "github.com/go-macaron/session"
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
"github.com/gogits/git-module"
"github.com/gogits/gogs/models" "github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/auth" "github.com/gogits/gogs/modules/auth"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
@ -43,7 +44,7 @@ type RepoContext struct {
CommitID string CommitID string
RepoLink string RepoLink string
CloneLink models.CloneLink CloneLink models.CloneLink
CommitsCount int CommitsCount int64
Mirror *models.Mirror Mirror *models.Mirror
} }

15
modules/middleware/repo.go

@ -11,8 +11,9 @@ import (
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
"github.com/gogits/git-module"
"github.com/gogits/gogs/models" "github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
@ -257,9 +258,9 @@ func RepoRef() macaron.Handler {
} }
refName = brs[0] refName = brs[0]
} }
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfBranch(refName) ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
if err != nil { if err != nil {
ctx.Handle(500, "GetCommitOfBranch", err) ctx.Handle(500, "GetBranchCommit", err)
return return
} }
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
@ -288,18 +289,18 @@ func RepoRef() macaron.Handler {
if ctx.Repo.GitRepo.IsBranchExist(refName) { if ctx.Repo.GitRepo.IsBranchExist(refName) {
ctx.Repo.IsViewBranch = true ctx.Repo.IsViewBranch = true
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfBranch(refName) ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
if err != nil { if err != nil {
ctx.Handle(500, "GetCommitOfBranch", err) ctx.Handle(500, "GetBranchCommit", err)
return return
} }
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
} else if ctx.Repo.GitRepo.IsTagExist(refName) { } else if ctx.Repo.GitRepo.IsTagExist(refName) {
ctx.Repo.IsViewTag = true ctx.Repo.IsViewTag = true
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfTag(refName) ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refName)
if err != nil { if err != nil {
ctx.Handle(500, "GetCommitOfTag", err) ctx.Handle(500, "GetTagCommit", err)
return return
} }
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()

10
modules/setting/setting.go

@ -59,6 +59,7 @@ var (
Protocol Scheme Protocol Scheme
Domain string Domain string
HttpAddr, HttpPort string HttpAddr, HttpPort string
LocalUrl string
DisableSSH bool DisableSSH bool
StartSSHServer bool StartSSHServer bool
SSHDomain string SSHDomain string
@ -97,6 +98,7 @@ var (
Repository struct { Repository struct {
AnsiCharset string AnsiCharset string
ForcePrivate bool ForcePrivate bool
MaxCreationLimit int
PullRequestQueueLength int PullRequestQueueLength int
} }
RepoRootPath string RepoRootPath string
@ -162,6 +164,7 @@ var (
Enabled bool Enabled bool
RunAtStart bool RunAtStart bool
Schedule string Schedule string
Timeout time.Duration
Args []string `delim:" "` Args []string `delim:" "`
} `ini:"cron.repo_health_check"` } `ini:"cron.repo_health_check"`
CheckRepoStats struct { CheckRepoStats struct {
@ -299,6 +302,7 @@ func NewContext() {
Domain = sec.Key("DOMAIN").MustString("localhost") Domain = sec.Key("DOMAIN").MustString("localhost")
HttpAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0") HttpAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0")
HttpPort = sec.Key("HTTP_PORT").MustString("3000") HttpPort = sec.Key("HTTP_PORT").MustString("3000")
LocalUrl = sec.Key("LOCAL_ROOT_URL").MustString("http://localhost:" + HttpPort + "/")
DisableSSH = sec.Key("DISABLE_SSH").MustBool() DisableSSH = sec.Key("DISABLE_SSH").MustBool()
if !DisableSSH { if !DisableSSH {
StartSSHServer = sec.Key("START_SSH_SERVER").MustBool() StartSSHServer = sec.Key("START_SSH_SERVER").MustBool()
@ -376,9 +380,9 @@ func NewContext() {
RepoRootPath = path.Clean(RepoRootPath) RepoRootPath = path.Clean(RepoRootPath)
} }
ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash") ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
Repository.AnsiCharset = sec.Key("ANSI_CHARSET").String() if err = Cfg.Section("repository").MapTo(&Repository); err != nil {
Repository.ForcePrivate = sec.Key("FORCE_PRIVATE").MustBool() log.Fatal(4, "Fail to map Repository settings: %v", err)
Repository.PullRequestQueueLength = sec.Key("PULL_REQUEST_QUEUE_LENGTH").MustInt(10000) }
// UI settings. // UI settings.
sec = Cfg.Section("ui") sec = Cfg.Section("ui")

5
modules/ssh/ssh.go

@ -1,5 +1,3 @@
// +build go1.4
// Copyright 2014 The Gogs Authors. All rights reserved. // Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -53,7 +51,8 @@ func handleServerConn(keyID string, chans <-chan ssh.NewChannel) {
case "env": case "env":
args := strings.Split(strings.Replace(payload, "\x00", "", -1), "\v") args := strings.Split(strings.Replace(payload, "\x00", "", -1), "\v")
if len(args) != 2 { if len(args) != 2 {
return log.Warn("Invalid env arguments: '%#v'", args)
continue
} }
args[0] = strings.TrimLeft(args[0], "\x04") args[0] = strings.TrimLeft(args[0], "\x04")
_, _, err := com.ExecCmdBytes("env", args[0]+"="+args[1]) _, _, err := com.ExecCmdBytes("env", args[0]+"="+args[1])

7
modules/ssh/ssh_1.3.go

@ -1,7 +0,0 @@
// +build !go1.4
package ssh
func Listen(port int) {
panic("Gogs requires Go 1.4 for starting a SSH server")
}

9
modules/template/template.go

@ -34,6 +34,9 @@ var Funcs template.FuncMap = map[string]interface{}{
"AppSubUrl": func() string { "AppSubUrl": func() string {
return setting.AppSubUrl return setting.AppSubUrl
}, },
"AppUrl": func() string {
return setting.AppUrl
},
"AppVer": func() string { "AppVer": func() string {
return setting.AppVer return setting.AppVer
}, },
@ -127,11 +130,7 @@ func Sha1(str string) string {
} }
func ToUtf8WithErr(content []byte) (error, string) { func ToUtf8WithErr(content []byte) (error, string) {
charsetLabel, err := base.DetectEncoding(content) charsetLabel := base.DetectEncoding(content)
if err != nil {
return err, ""
}
if charsetLabel == "UTF-8" { if charsetLabel == "UTF-8" {
return nil, string(content) return nil, string(content)
} }

37
packager/debian/postinst vendored

@ -1,37 +0,0 @@
#!/bin/sh
set -e
APP_NAME="gogs"
CLI="${APP_NAME}"
APP_USER=$(${CLI} config:get APP_USER)
APP_GROUP=$(${CLI} config:get APP_GROUP)
APP_CONFIG="/etc/${APP_NAME}/conf/app.ini"
case "$1" in
abort-upgrade|abort-remove|abort-deconfigure)
exit 0
;;
configure|*)
mkdir -p $(dirname ${APP_CONFIG})
chown ${APP_USER}.${APP_GROUP} $(dirname ${APP_CONFIG})
[ -f ${APP_CONFIG} ] || ${CLI} run cp conf/app.ini ${APP_CONFIG}
${CLI} config:set USER=${APP_USER}
sed -i "s|RUN_USER = git|RUN_USER = ${APP_USER}|" ${APP_CONFIG}
sed -i "s|RUN_MODE = dev|RUN_MODE = prod|" ${APP_CONFIG}
# setup symlink towards custom conf
mkdir -p /opt/${APP_NAME}/custom/conf
chown -R ${APP_USER}.${APP_GROUP} /opt/${APP_NAME}/custom
ln -f -s ${APP_CONFIG} /opt/${APP_NAME}/custom/conf/app.ini
# scale
${CLI} scale web=1 || true
# restart the service
service gogs restart || true
;;
esac

24
packager/hooks/postinst

@ -0,0 +1,24 @@
#!/bin/sh
set -e
APP_NAME="gogs"
CLI="${APP_NAME}"
APP_USER=$(${CLI} config:get APP_USER)
APP_GROUP=$(${CLI} config:get APP_GROUP)
APP_CONFIG="/etc/${APP_NAME}/conf/app.ini"
mkdir -p $(dirname ${APP_CONFIG})
chown ${APP_USER}.${APP_GROUP} $(dirname ${APP_CONFIG})
[ -f ${APP_CONFIG} ] || ${CLI} run cp conf/app.ini ${APP_CONFIG}
${CLI} config:set USER=${APP_USER}
sed -i "s|RUN_USER = git|RUN_USER = ${APP_USER}|" ${APP_CONFIG}
sed -i "s|RUN_MODE = dev|RUN_MODE = prod|" ${APP_CONFIG}
${CLI} config:set GOGS_CUSTOM=/etc/${APP_NAME}
# scale
${CLI} scale web=1 || true
# restart the service
service gogs restart || true

8
public/config.codekit

@ -47,20 +47,20 @@
"outputPathIsOutsideProject": 0, "outputPathIsOutsideProject": 0,
"outputPathIsSetByUser": 0 "outputPathIsSetByUser": 0
}, },
"\/css\/highlight-8.9.1\/default.css": { "\/css\/highlight-9.0.0\/default.css": {
"fileType": 16, "fileType": 16,
"ignore": 0, "ignore": 0,
"ignoreWasSetByUser": 0, "ignoreWasSetByUser": 0,
"inputAbbreviatedPath": "\/css\/highlight-8.9.1\/default.css", "inputAbbreviatedPath": "\/css\/highlight-9.0.0\/default.css",
"outputAbbreviatedPath": "No Output Path", "outputAbbreviatedPath": "No Output Path",
"outputPathIsOutsideProject": 0, "outputPathIsOutsideProject": 0,
"outputPathIsSetByUser": 0 "outputPathIsSetByUser": 0
}, },
"\/css\/highlight-8.9.1\/github.css": { "\/css\/highlight-9.0.0\/github.css": {
"fileType": 16, "fileType": 16,
"ignore": 0, "ignore": 0,
"ignoreWasSetByUser": 0, "ignoreWasSetByUser": 0,
"inputAbbreviatedPath": "\/css\/highlight-8.9.1\/github.css", "inputAbbreviatedPath": "\/css\/highlight-9.0.0\/github.css",
"outputAbbreviatedPath": "No Output Path", "outputAbbreviatedPath": "No Output Path",
"outputPathIsOutsideProject": 0, "outputPathIsOutsideProject": 0,
"outputPathIsSetByUser": 0 "outputPathIsSetByUser": 0

57
public/css/gogs.css

@ -896,10 +896,10 @@ pre.raw {
border-color: #F0C36D; border-color: #F0C36D;
} }
.ui .info.segment { .ui .info.segment {
border-color: #85c5e5; border: 1px solid #c5d5dd;
} }
.ui .info.segment.top { .ui .info.segment.top {
background-color: #d9edf7 !important; background-color: #e6f1f6 !important;
} }
.ui .info.segment.top h3, .ui .info.segment.top h3,
.ui .info.segment.top h4 { .ui .info.segment.top h4 {
@ -1097,7 +1097,7 @@ footer .container .links > *:first-child {
word-wrap: break-word; word-wrap: break-word;
} }
.markdown.file-view { .markdown.file-view {
padding: 5px 2em 2em !important; padding: 2em 2em 2em !important;
} }
.markdown > *:first-child { .markdown > *:first-child {
margin-top: 0 !important; margin-top: 0 !important;
@ -1136,6 +1136,14 @@ footer .container .links > *:first-child {
font-weight: bold; font-weight: bold;
line-height: 1.4; line-height: 1.4;
} }
.markdown h1:first-of-type,
.markdown h2:first-of-type,
.markdown h3:first-of-type,
.markdown h4:first-of-type,
.markdown h5:first-of-type,
.markdown h6:first-of-type {
margin-top: 0 !important;
}
.markdown h1 .octicon-link, .markdown h1 .octicon-link,
.markdown h2 .octicon-link, .markdown h2 .octicon-link,
.markdown h3 .octicon-link, .markdown h3 .octicon-link,
@ -1303,7 +1311,7 @@ footer .container .links > *:first-child {
.markdown table th, .markdown table th,
.markdown table td { .markdown table td {
padding: 6px 13px !important; padding: 6px 13px !important;
border: 1px solid #ddd; border: 1px solid #ddd !important;
} }
.markdown table tr { .markdown table tr {
background-color: #fff; background-color: #fff;
@ -1773,9 +1781,9 @@ footer .container .links > *:first-child {
} }
.repository .head .fork-flag { .repository .head .fork-flag {
margin-left: 38px; margin-left: 38px;
margin-top: 3px;
display: block; display: block;
font-size: 12px; font-size: 12px;
line-height: 10px;
white-space: nowrap; white-space: nowrap;
} }
.repository .navbar .ui.label { .repository .navbar .ui.label {
@ -1900,8 +1908,8 @@ footer .container .links > *:first-child {
padding: 5px 5px 0 5px; padding: 5px 5px 0 5px;
} }
.repository.file.list #file-content .code-view * { .repository.file.list #file-content .code-view * {
font-size: 13px; font-size: 12px;
font-family: monospace; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
line-height: 20px; line-height: 20px;
} }
.repository.file.list #file-content .code-view table { .repository.file.list #file-content .code-view table {
@ -1915,7 +1923,6 @@ footer .container .links > *:first-child {
width: 1%; width: 1%;
} }
.repository.file.list #file-content .code-view .lines-num span { .repository.file.list #file-content .code-view .lines-num span {
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
line-height: 20px; line-height: 20px;
padding: 0 10px; padding: 0 10px;
cursor: pointer; cursor: pointer;
@ -2310,11 +2317,11 @@ footer .container .links > *:first-child {
color: #888; color: #888;
} }
.repository .diff-file-box .header { .repository .diff-file-box .header {
border-bottom: 1px solid #d4d4d5!important; background-color: #f7f7f7;
} }
.repository .diff-file-box .file-body.file-code .lines-num { .repository .diff-file-box .file-body.file-code .lines-num {
text-align: right; text-align: right;
color: #999; color: #A7A7A7;
background: #fafafa; background: #fafafa;
width: 1%; width: 1%;
} }
@ -2322,15 +2329,15 @@ footer .container .links > *:first-child {
border-right: 1px solid #DDD; border-right: 1px solid #DDD;
} }
.repository .diff-file-box .code-diff { .repository .diff-file-box .code-diff {
font-size: 13px; font-size: 12px;
} }
.repository .diff-file-box .code-diff td { .repository .diff-file-box .code-diff td {
padding: 0; padding: 0;
padding-left: 10px;
border-top: none; border-top: none;
} }
.repository .diff-file-box .code-diff pre { .repository .diff-file-box .code-diff pre {
margin: 0; margin: 0;
font-size: 13px;
} }
.repository .diff-file-box .code-diff .lines-num { .repository .diff-file-box .code-diff .lines-num {
border-right: 1px solid #d4d4d5; border-right: 1px solid #d4d4d5;
@ -2338,25 +2345,20 @@ footer .container .links > *:first-child {
} }
.repository .diff-file-box .code-diff tbody tr.tag-code td, .repository .diff-file-box .code-diff tbody tr.tag-code td,
.repository .diff-file-box .code-diff tbody tr.tag-code pre { .repository .diff-file-box .code-diff tbody tr.tag-code pre {
background-color: #E0E0E0 !important; background-color: #F0F0F0 !important;
border-color: #ADADAD!important; border-color: #D2CECE!important;
padding-top: 4px;
padding-bottom: 4px;
} }
.repository .diff-file-box .code-diff tbody tr.del-code td, .repository .diff-file-box .code-diff tbody tr.del-code td,
.repository .diff-file-box .code-diff tbody tr.del-code pre { .repository .diff-file-box .code-diff tbody tr.del-code pre {
background-color: #ffe2dd !important; background-color: #ffecec !important;
border-color: #e9aeae !important; border-color: #f1c0c0 !important;
} }
.repository .diff-file-box .code-diff tbody tr.add-code td, .repository .diff-file-box .code-diff tbody tr.add-code td,
.repository .diff-file-box .code-diff tbody tr.add-code pre { .repository .diff-file-box .code-diff tbody tr.add-code pre {
background-color: #d1ffd6 !important; background-color: #eaffea !important;
border-color: #b4e2b4 !important; border-color: #c1e9c1 !important;
}
.repository .diff-file-box .code-diff tbody tr:hover td {
background-color: #FFF8D2 !important;
border-color: #F0DB88 !important;
}
.repository .diff-file-box .code-diff tbody tr:hover pre {
background-color: transparent !important;
} }
.repository .diff-file-box.file-content img { .repository .diff-file-box.file-content img {
max-width: 100%; max-width: 100%;
@ -2773,7 +2775,6 @@ footer .container .links > *:first-child {
width: 50%!important; width: 50%!important;
} }
.organization.options input { .organization.options input {
width: 50%!important;
min-width: 300px; min-width: 300px;
} }
.organization.profile #org-avatar { .organization.profile #org-avatar {
@ -2981,6 +2982,10 @@ footer .container .links > *:first-child {
padding-top: 10px; padding-top: 10px;
padding-bottom: 5px; padding-bottom: 5px;
} }
.feeds .list .header .plus.icon {
margin-top: 5px;
margin-right: 0;
}
.feeds .list ul { .feeds .list ul {
list-style: none; list-style: none;
margin: 0; margin: 0;

123
public/css/highlight-8.9.1/github.css

@ -1,123 +0,0 @@
/*
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
-webkit-text-size-adjust: none;
}
.hljs-comment,
.diff .hljs-header {
color: #998;
font-style: italic;
}
.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
color: #008080;
}
.hljs-string,
.hljs-tag .hljs-value,
.hljs-doctag,
.tex .hljs-formula {
color: #d14;
}
.hljs-title,
.hljs-id,
.scss .hljs-preprocessor {
color: #900;
font-weight: bold;
}
.hljs-list .hljs-keyword,
.hljs-subst {
font-weight: normal;
}
.hljs-class .hljs-title,
.hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rule .hljs-property,
.django .hljs-tag .hljs-keyword {
color: #000080;
font-weight: normal;
}
.hljs-attribute,
.hljs-variable,
.lisp .hljs-body,
.hljs-name {
color: #008080;
}
.hljs-regexp {
color: #009926;
}
.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.clojure .hljs-keyword,
.scheme .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
color: #990073;
}
.hljs-built_in {
color: #0086b3;
}
.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.diff .hljs-change {
background: #0086b3;
}
.hljs-chunk {
color: #aaa;
}

0
public/css/highlight-8.9.1/default.css → public/css/highlight-9.0.0/default.css

99
public/css/highlight-9.0.0/github.css

@ -0,0 +1,99 @@
/*
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
}
.hljs-comment,
.hljs-quote {
color: #998;
font-style: italic;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-subst {
color: #333;
font-weight: bold;
}
.hljs-number,
.hljs-literal,
.hljs-variable,
.hljs-template-variable,
.hljs-tag .hljs-attr {
color: #008080;
}
.hljs-string,
.hljs-doctag {
color: #d14;
}
.hljs-title,
.hljs-section,
.hljs-selector-id {
color: #900;
font-weight: bold;
}
.hljs-subst {
font-weight: normal;
}
.hljs-type,
.hljs-class .hljs-title {
color: #458;
font-weight: bold;
}
.hljs-tag,
.hljs-name,
.hljs-attribute {
color: #000080;
font-weight: normal;
}
.hljs-regexp,
.hljs-link {
color: #009926;
}
.hljs-symbol,
.hljs-bullet {
color: #990073;
}
.hljs-built_in,
.hljs-builtin-name {
color: #0086b3;
}
.hljs-meta {
color: #999;
font-weight: bold;
}
.hljs-deletion {
background: #fdd;
}
.hljs-addition {
background: #dfd;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

10
public/js/gogs.js

@ -411,7 +411,7 @@ function initRepository() {
$status_btn.click(function () { $status_btn.click(function () {
$('#status').val($status_btn.data('status-val')); $('#status').val($status_btn.data('status-val'));
$('#comment-form').submit(); $('#comment-form').submit();
}) });
} }
// Diff // Diff
@ -464,10 +464,7 @@ function initWiki() {
element: $edit_area[0], element: $edit_area[0],
previewRender: function (plainText, preview) { // Async method previewRender: function (plainText, preview) { // Async method
setTimeout(function () { setTimeout(function () {
if ($('.editor-preview-active').length == 0) { // FIXME: still send render request when return back to edit mode
return;
}
$.post($edit_area.data('url'), { $.post($edit_area.data('url'), {
"_csrf": csrf, "_csrf": csrf,
"mode": "gfm", "mode": "gfm",
@ -870,7 +867,8 @@ $(document).ready(function () {
// Emojify // Emojify
emojify.setConfig({ emojify.setConfig({
img_dir: suburl + '/img/emoji' img_dir: suburl + '/img/emoji',
ignore_emoticons: true
}); });
emojify.run(); emojify.run();

3
public/js/libs/highlight-8.9.1.pack.js

File diff suppressed because one or more lines are too long

4
public/js/libs/highlight-9.0.0.pack.js

File diff suppressed because one or more lines are too long

4
public/less/_base.less

@ -197,9 +197,9 @@ pre {
} }
.info { .info {
&.segment { &.segment {
border-color: #85c5e5; border: 1px solid #c5d5dd;
&.top { &.top {
background-color: #d9edf7 !important; background-color: #e6f1f6 !important;
h3, h4 { h3, h4 {
margin-top: 0; margin-top: 0;
} }

5
public/less/_dashboard.less

@ -89,6 +89,11 @@
.header { .header {
padding-top: 10px; padding-top: 10px;
padding-bottom: 5px; padding-bottom: 5px;
.plus.icon {
margin-top: 5px;
margin-right: 0;
}
} }
ul { ul {
list-style: none; list-style: none;

10
public/less/_markdown.less

@ -6,7 +6,7 @@
word-wrap: break-word; word-wrap: break-word;
&.file-view { &.file-view {
padding: 5px 2em 2em !important; padding: 2em 2em 2em !important;
} }
>*:first-child { >*:first-child {
@ -51,6 +51,10 @@
margin-bottom: 16px; margin-bottom: 16px;
font-weight: bold; font-weight: bold;
line-height: 1.4; line-height: 1.4;
&:first-of-type {
margin-top: 0 !important;
}
} }
h1 .octicon-link, h1 .octicon-link,
@ -249,8 +253,8 @@
table th, table th,
table td { table td {
padding:6px 13px !important; padding: 6px 13px !important;
border:1px solid #ddd; border: 1px solid #ddd !important;
} }
table tr { table tr {

1
public/less/_organization.less

@ -21,7 +21,6 @@
&.options { &.options {
input { input {
width: 50%!important;
min-width: 300px; min-width: 300px;
} }
} }

39
public/less/_repository.less

@ -25,9 +25,9 @@
} }
.fork-flag { .fork-flag {
margin-left: @mega-octicon-width + 8px; margin-left: @mega-octicon-width + 8px;
margin-top: 3px;
display: block; display: block;
font-size: 12px; font-size: 12px;
line-height: 10px;
white-space: nowrap; white-space: nowrap;
} }
} }
@ -190,8 +190,8 @@
.code-view { .code-view {
* { * {
font-size: 13px; font-size: 12px;
font-family: monospace; font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
line-height: 20px; line-height: 20px;
} }
@ -206,7 +206,6 @@
width: 1%; width: 1%;
span { span {
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
line-height: 20px; line-height: 20px;
padding: 0 10px; padding: 0 10px;
cursor: pointer; cursor: pointer;
@ -661,12 +660,12 @@
} }
.diff-file-box { .diff-file-box {
.header { .header {
border-bottom: 1px solid #d4d4d5!important; background-color: #f7f7f7;
} }
.file-body.file-code { .file-body.file-code {
.lines-num { .lines-num {
text-align: right; text-align: right;
color: #999; color: #A7A7A7;
background: #fafafa; background: #fafafa;
width: 1%; width: 1%;
} }
@ -675,15 +674,15 @@
} }
} }
.code-diff { .code-diff {
font-size: 13px; font-size: 12px;
td { td {
padding: 0; padding: 0;
padding-left: 10px;
border-top: none; border-top: none;
} }
pre { pre {
margin: 0; margin: 0;
font-size: 13px;
} }
.lines-num { .lines-num {
border-right: 1px solid #d4d4d5; border-right: 1px solid #d4d4d5;
@ -691,10 +690,13 @@
} }
tbody { tbody {
tr { tr {
&.tag-code { &.tag-code {
td, pre { td, pre {
background-color: #E0E0E0 !important; background-color: #F0F0F0 !important;
border-color: #ADADAD!important; border-color: #D2CECE!important;
padding-top: 4px;
padding-bottom: 4px;
} }
// td.selected-line, td.selected-line pre { // td.selected-line, td.selected-line pre {
// background-color: #ffffdd !important; // background-color: #ffffdd !important;
@ -707,8 +709,8 @@
// } // }
&.del-code { &.del-code {
td, pre { td, pre {
background-color: #ffe2dd !important; background-color: #ffecec !important;
border-color: #e9aeae !important; border-color: #f1c0c0 !important;
} }
// td.selected-line, td.selected-line pre { // td.selected-line, td.selected-line pre {
// background-color: #ffffdd !important; // background-color: #ffffdd !important;
@ -716,22 +718,13 @@
} }
&.add-code { &.add-code {
td, pre { td, pre {
background-color: #d1ffd6 !important; background-color: #eaffea !important;
border-color: #b4e2b4 !important; border-color: #c1e9c1 !important;
} }
// td.selected-line, td.selected-line pre { // td.selected-line, td.selected-line pre {
// background-color: #ffffdd !important; // background-color: #ffffdd !important;
// } // }
} }
&:hover {
td {
background-color: #FFF8D2 !important;
border-color: #F0DB88 !important;
}
pre {
background-color: transparent !important;
}
}
} }
} }
} }

24
routers/admin/auths.go

@ -45,10 +45,10 @@ type AuthSource struct {
} }
var authSources = []AuthSource{ var authSources = []AuthSource{
{models.LoginNames[models.LDAP], models.LDAP}, {models.LoginNames[models.LOGIN_LDAP], models.LOGIN_LDAP},
{models.LoginNames[models.DLDAP], models.DLDAP}, {models.LoginNames[models.LOGIN_DLDAP], models.LOGIN_DLDAP},
{models.LoginNames[models.SMTP], models.SMTP}, {models.LoginNames[models.LOGIN_SMTP], models.LOGIN_SMTP},
{models.LoginNames[models.PAM], models.PAM}, {models.LoginNames[models.LOGIN_PAM], models.LOGIN_PAM},
} }
func NewAuthSource(ctx *middleware.Context) { func NewAuthSource(ctx *middleware.Context) {
@ -56,8 +56,8 @@ func NewAuthSource(ctx *middleware.Context) {
ctx.Data["PageIsAdmin"] = true ctx.Data["PageIsAdmin"] = true
ctx.Data["PageIsAdminAuthentications"] = true ctx.Data["PageIsAdminAuthentications"] = true
ctx.Data["type"] = models.LDAP ctx.Data["type"] = models.LOGIN_LDAP
ctx.Data["CurTypeName"] = models.LoginNames[models.LDAP] ctx.Data["CurTypeName"] = models.LoginNames[models.LOGIN_LDAP]
ctx.Data["smtp_auth"] = "PLAIN" ctx.Data["smtp_auth"] = "PLAIN"
ctx.Data["is_active"] = true ctx.Data["is_active"] = true
ctx.Data["AuthSources"] = authSources ctx.Data["AuthSources"] = authSources
@ -115,11 +115,11 @@ func NewAuthSourcePost(ctx *middleware.Context, form auth.AuthenticationForm) {
var config core.Conversion var config core.Conversion
switch models.LoginType(form.Type) { switch models.LoginType(form.Type) {
case models.LDAP, models.DLDAP: case models.LOGIN_LDAP, models.LOGIN_DLDAP:
config = parseLDAPConfig(form) config = parseLDAPConfig(form)
case models.SMTP: case models.LOGIN_SMTP:
config = parseSMTPConfig(form) config = parseSMTPConfig(form)
case models.PAM: case models.LOGIN_PAM:
config = &models.PAMConfig{ config = &models.PAMConfig{
ServiceName: form.PAMServiceName, ServiceName: form.PAMServiceName,
} }
@ -181,11 +181,11 @@ func EditAuthSourcePost(ctx *middleware.Context, form auth.AuthenticationForm) {
var config core.Conversion var config core.Conversion
switch models.LoginType(form.Type) { switch models.LoginType(form.Type) {
case models.LDAP, models.DLDAP: case models.LOGIN_LDAP, models.LOGIN_DLDAP:
config = parseLDAPConfig(form) config = parseLDAPConfig(form)
case models.SMTP: case models.LOGIN_SMTP:
config = parseSMTPConfig(form) config = parseSMTPConfig(form)
case models.PAM: case models.LOGIN_PAM:
config = &models.PAMConfig{ config = &models.PAMConfig{
ServiceName: form.PAMServiceName, ServiceName: form.PAMServiceName,
} }

3
routers/admin/users.go

@ -90,7 +90,7 @@ func NewUserPost(ctx *middleware.Context, form auth.AdminCrateUserForm) {
Email: form.Email, Email: form.Email,
Passwd: form.Password, Passwd: form.Password,
IsActive: true, IsActive: true,
LoginType: models.PLAIN, LoginType: models.LOGIN_PLAIN,
} }
if len(form.LoginType) > 0 { if len(form.LoginType) > 0 {
@ -210,6 +210,7 @@ func EditUserPost(ctx *middleware.Context, form auth.AdminEditUserForm) {
u.Email = form.Email u.Email = form.Email
u.Website = form.Website u.Website = form.Website
u.Location = form.Location u.Location = form.Location
u.MaxRepoCreation = form.MaxRepoCreation
u.IsActive = form.Active u.IsActive = form.Active
u.IsAdmin = form.Admin u.IsAdmin = form.Admin
u.AllowGitHook = form.AllowGitHook u.AllowGitHook = form.AllowGitHook

2
routers/api/v1/admin/users.go

@ -43,7 +43,7 @@ func CreateUser(ctx *middleware.Context, form api.CreateUserOption) {
Email: form.Email, Email: form.Email,
Passwd: form.Password, Passwd: form.Password,
IsActive: true, IsActive: true,
LoginType: models.PLAIN, LoginType: models.LOGIN_PLAIN,
} }
parseLoginSource(ctx, u, form.SourceID, form.LoginName) parseLoginSource(ctx, u, form.SourceID, form.LoginName)

3
routers/api/v1/api.go

@ -144,6 +144,9 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Combo("/:id").Get(user.GetPublicKey). m.Combo("/:id").Get(user.GetPublicKey).
Delete(user.DeletePublicKey) Delete(user.DeletePublicKey)
}) })
m.Combo("/emails").Get(user.ListEmails).
Post(bind(api.CreateEmailOption{}), user.AddEmail).
Delete(bind(api.CreateEmailOption{}), user.DeleteEmail)
}, ReqToken()) }, ReqToken())
// Repositories // Repositories

5
routers/api/v1/repo/file.go

@ -5,8 +5,9 @@
package repo package repo
import ( import (
"github.com/gogits/git-module"
"github.com/gogits/gogs/models" "github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/middleware" "github.com/gogits/gogs/modules/middleware"
"github.com/gogits/gogs/routers/repo" "github.com/gogits/gogs/routers/repo"
) )
@ -20,7 +21,7 @@ func GetRawFile(ctx *middleware.Context) {
blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreeName) blob, err := ctx.Repo.Commit.GetBlobByPath(ctx.Repo.TreeName)
if err != nil { if err != nil {
if err == git.ErrNotExist { if git.IsErrNotExist(err) {
ctx.Error(404) ctx.Error(404)
} else { } else {
ctx.APIError(500, "GetBlobByPath", err) ctx.APIError(500, "GetBlobByPath", err)

78
routers/api/v1/user/email.go

@ -0,0 +1,78 @@
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package user
import (
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/middleware"
"github.com/gogits/gogs/modules/setting"
to "github.com/gogits/gogs/routers/api/v1/utils"
)
func ListEmails(ctx *middleware.Context) {
emails, err := models.GetEmailAddresses(ctx.User.Id)
if err != nil {
ctx.Handle(500, "GetEmailAddresses", err)
return
}
apiEmails := make([]*api.Email, len(emails))
for i := range emails {
apiEmails[i] = to.ApiEmail(emails[i])
}
ctx.JSON(200, &apiEmails)
}
func AddEmail(ctx *middleware.Context, form api.CreateEmailOption) {
if len(form.Emails) == 0 {
ctx.Status(422)
return
}
emails := make([]*models.EmailAddress, len(form.Emails))
for i := range form.Emails {
emails[i] = &models.EmailAddress{
UID: ctx.User.Id,
Email: form.Emails[i],
IsActivated: !setting.Service.RegisterEmailConfirm,
}
}
if err := models.AddEmailAddresses(emails); err != nil {
if models.IsErrEmailAlreadyUsed(err) {
ctx.APIError(422, "", "Email address has been used: "+err.(models.ErrEmailAlreadyUsed).Email)
} else {
ctx.APIError(500, "AddEmailAddresses", err)
}
return
}
apiEmails := make([]*api.Email, len(emails))
for i := range emails {
apiEmails[i] = to.ApiEmail(emails[i])
}
ctx.JSON(201, &apiEmails)
}
func DeleteEmail(ctx *middleware.Context, form api.CreateEmailOption) {
if len(form.Emails) == 0 {
ctx.Status(204)
return
}
emails := make([]*models.EmailAddress, len(form.Emails))
for i := range form.Emails {
emails[i] = &models.EmailAddress{
Email: form.Emails[i],
}
}
if err := models.DeleteEmailAddresses(emails); err != nil {
ctx.APIError(500, "DeleteEmailAddresses", err)
return
}
ctx.Status(204)
}

8
routers/api/v1/utils/convert.go

@ -26,6 +26,14 @@ func ApiUser(u *models.User) *api.User {
} }
} }
func ApiEmail(email *models.EmailAddress) *api.Email {
return &api.Email{
Email: email.Email,
Verified: email.IsActivated,
Primary: email.IsPrimary,
}
}
// ApiRepository converts repository to API format. // ApiRepository converts repository to API format.
func ApiRepository(owner *models.User, repo *models.Repository, permission api.Permission) *api.Repository { func ApiRepository(owner *models.User, repo *models.Repository, permission api.Permission) *api.Repository {
cl := repo.CloneLink() cl := repo.CloneLink()

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save