Browse Source

Merge branch 'develop' of github.com:gogits/gogs into release/0.6.1

pull/1105/head
Unknwon 10 years ago
parent
commit
62e436e6b7
  1. 1
      .bra.toml
  2. 12
      .editorconfig
  3. 22
      .gobuild.yml
  4. 38
      .gopmfile
  5. 17
      Dockerfile
  6. 12
      README.md
  7. 8
      README_ZH.md
  8. 2
      cmd/serve.go
  9. 20
      cmd/web.go
  10. 7
      conf/README
  11. 6
      conf/app.ini
  12. BIN
      conf/content/git-bare.zip
  13. 3
      conf/locale/TRANSLATORS
  14. 21
      conf/locale/locale_de-DE.ini
  15. 93
      conf/locale/locale_en-US.ini
  16. 21
      conf/locale/locale_es-ES.ini
  17. 21
      conf/locale/locale_fr-CA.ini
  18. 21
      conf/locale/locale_ja-JP.ini
  19. 21
      conf/locale/locale_lv-LV.ini
  20. 21
      conf/locale/locale_nl-NL.ini
  21. 727
      conf/locale/locale_pt-BR.ini
  22. 27
      conf/locale/locale_ru-RU.ini
  23. 21
      conf/locale/locale_zh-CN.ini
  24. 27
      conf/locale/locale_zh-HK.ini
  25. 12
      docker-compose.yml
  26. 2
      gogs.go
  27. 6
      models/access.go
  28. 86
      models/action.go
  29. 84
      models/error.go
  30. 6
      models/login.go
  31. 5
      models/migrations/migrations.go
  32. 9
      models/models.go
  33. 35
      models/org.go
  34. 9
      models/publickey.go
  35. 168
      models/repo.go
  36. 89
      models/user.go
  37. 2
      models/webhook.go
  38. 18
      modules/auth/admin.go
  39. 14
      modules/auth/repo_form.go
  40. 2
      modules/base/tool.go
  41. 1041
      modules/bindata/bindata.go
  42. 4
      modules/git/commit.go
  43. 4
      modules/git/submodule.go
  44. 2
      modules/mailer/mail.go
  45. 2
      modules/middleware/auth.go
  46. 4
      modules/middleware/repo.go
  47. 24
      modules/setting/setting.go
  48. 32
      public/ng/css/gogs.css
  49. 37
      public/ng/css/ui.css
  50. 3
      public/ng/less/gogs/dashboard.less
  51. 28
      public/ng/less/gogs/issue.less
  52. 31
      public/ng/less/ui/form.less
  53. 7
      public/ng/less/ui/menu.less
  54. 4
      public/ng/less/ui/reset.less
  55. 4
      public/ng/less/ui/var.less
  56. 13
      routers/admin/users.go
  57. 6
      routers/api/v1/repo.go
  58. 4
      routers/org/members.go
  59. 7
      routers/org/setting.go
  60. 4
      routers/org/teams.go
  61. 47
      routers/repo/http.go
  62. 8
      routers/repo/issue.go
  63. 12
      routers/repo/repo.go
  64. 3
      routers/repo/setting.go
  65. 6
      routers/repo/view.go
  66. 15
      routers/user/home.go
  67. 17
      routers/user/setting.go
  68. 12
      scripts/init/centos/gogs
  69. 2
      templates/.VERSION
  70. 2
      templates/admin/auth/edit.tmpl
  71. 2
      templates/admin/user/edit.tmpl
  72. 6
      templates/ng/base/alert.tmpl
  73. 2
      templates/repo/bare.tmpl
  74. 4
      templates/repo/migrate.tmpl
  75. 4
      templates/repo/view_list.tmpl
  76. 14
      templates/user/dashboard/feeds.tmpl
  77. 95
      templates/user/issues.tmpl
  78. 1
      wercker.yml

1
.bra.toml

@ -14,6 +14,7 @@ watch_dirs = [
watch_exts = [".go", ".ini"] watch_exts = [".go", ".ini"]
build_delay = 1500 build_delay = 1500
cmds = [ cmds = [
#["go-bindata", "-o=modules/bindata/bindata.go", "-ignore=\\.DS_Store|README", "-pkg=bindata", "conf/..."],
["go", "install", "-tags", "sqlite cert"],# redis memcache ["go", "install", "-tags", "sqlite cert"],# redis memcache
["go", "build", "-tags", "sqlite cert"], ["go", "build", "-tags", "sqlite cert"],
["./gogs", "web"] ["./gogs", "web"]

12
.editorconfig

@ -0,0 +1,12 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = tab
[*.yml]
indent_style = space
indent_size = 2

22
.gobuild.yml

@ -1,22 +0,0 @@
filesets:
includes:
- conf
- etc
- public
- scripts
- templates
- LICENSE
- README.md
- README_ZH.md
excludes:
- \.git
depth: 5
settings:
build: |
if test "$GOOS" = "windows" -a "$GOARCH" = "386"
then
go install -v
else
go get -v -tags "sqlite redis memcache cert" github.com/gogits/gogs
go install -v -tags "sqlite redis memcache cert"
fi

38
.gopmfile

@ -5,33 +5,33 @@ path = github.com/gogits/gogs
github.com/bradfitz/gomemcache = commit:72a68649ba github.com/bradfitz/gomemcache = commit:72a68649ba
github.com/Unknwon/cae = commit:2e70a1351b github.com/Unknwon/cae = commit:2e70a1351b
github.com/Unknwon/com = commit:188d690b1a github.com/Unknwon/com = commit:188d690b1a
github.com/Unknwon/i18n = commit:1e88666229 github.com/Unknwon/i18n = commit:7457d88830
github.com/Unknwon/macaron = commit:e089393c3f github.com/Unknwon/macaron = commit:93de4f3fad
github.com/codegangsta/cli = commit:6086d7927e github.com/codegangsta/cli = commit:2bcd11f863
github.com/go-sql-driver/mysql = commit:27633f0519 github.com/go-sql-driver/mysql = commit:a197e5d405
github.com/go-xorm/core = commit:16cb27928f github.com/go-xorm/core = commit:be6e7ac47d
github.com/go-xorm/xorm = commit:f2d3be988e github.com/go-xorm/xorm = commit:1f0dd9bef2
github.com/gogits/chardet = commit:2404f77725 github.com/gogits/chardet = commit:2404f77725
github.com/gogits/go-gogs-client = commit:92e76d616a github.com/gogits/go-gogs-client = commit:92e76d616a
github.com/lib/pq = commit:835d5eb08d github.com/lib/pq = commit:30ed2200d7
github.com/macaron-contrib/binding = commit:dc739fabc3 github.com/macaron-contrib/binding = commit:548a793679
github.com/macaron-contrib/cache = commit:b68f6b448f github.com/macaron-contrib/cache = commit:928d5c35cd
github.com/macaron-contrib/captcha = commit:066c50c7eb github.com/macaron-contrib/captcha = commit:fbb8b1ebb5
github.com/macaron-contrib/csrf = commit:98ddf5a710 github.com/macaron-contrib/csrf = commit:98ddf5a710
github.com/macaron-contrib/i18n = commit:eeebd44f64 github.com/macaron-contrib/i18n = commit:627d60fe6f
github.com/macaron-contrib/oauth2 = commit:8f394c3629 github.com/macaron-contrib/oauth2 = commit:8f394c3629
github.com/macaron-contrib/session = commit:8e8d938b27 github.com/macaron-contrib/session = commit:31e841d95c
github.com/macaron-contrib/toolbox = commit:acbfe36e16 github.com/macaron-contrib/toolbox = commit:acbfe36e16
github.com/mattn/go-sqlite3 = commit:25d045f12a github.com/mattn/go-sqlite3 = commit:5253daf856
github.com/microcosm-cc/bluemonday = commit:fcd0f5074e github.com/microcosm-cc/bluemonday = commit:fcd0f5074e
github.com/nfnt/resize = commit:8f44931448 github.com/nfnt/resize = commit:53e9ca890b
github.com/russross/blackfriday = commit:77efab57b2 github.com/russross/blackfriday = commit:6928e11ecd
github.com/shurcooL/go = commit:329f57438c github.com/shurcooL/go = commit:bc30a0bd33
golang.org/x/net = golang.org/x/net = commit:0b492c5a96
golang.org/x/text = golang.org/x/text = commit:c6bc7e82e2
gopkg.in/ini.v1 = commit:4febc4104c gopkg.in/ini.v1 = commit:4febc4104c
gopkg.in/redis.v2 = commit:e617904962 gopkg.in/redis.v2 = commit:e617904962
[res] [res]
include = conf|etc|public|scripts|templates include = etc|public|scripts|templates

17
Dockerfile

@ -0,0 +1,17 @@
FROM google/golang:latest
ENV TAGS="sqlite redis memcache cert" USER="git" HOME="/home/git"
COPY . /gopath/src/github.com/gogits/gogs/
WORKDIR /gopath/src/github.com/gogits/gogs/
RUN go get -v -tags="$TAGS" github.com/gogits/gogs \
&& go build -tags="$TAGS" \
&& useradd -d $HOME -m $USER \
&& chown -R $USER .
USER $USER
ENTRYPOINT [ "./gogs" ]
CMD [ "web" ]

12
README.md

@ -7,14 +7,14 @@ Gogs (Go Git Service) is a painless self-hosted Git service written in Go.
![Demo](http://gogs.qiniudn.com/gogs_demo.gif) ![Demo](http://gogs.qiniudn.com/gogs_demo.gif)
##### Current version: 0.5.16 Beta ##### Current version: 0.6.0 Beta
### 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. - 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.
- The demo site [try.gogs.io](https://try.gogs.io) is running under `dev` branch. - The demo site [try.gogs.io](https://try.gogs.io) is running under `develop` branch.
- You **MUST** read [CONTRIBUTING.md](CONTRIBUTING.md) before you start filing an issue or making a Pull Request. - 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 and feature Pull Reuqests, otherwise it's high possibilities that we are not going to merge it.
- 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!
#### Other language version #### Other language version
@ -30,7 +30,7 @@ The goal of this project is to make the easiest, fastest, and most painless way
- See the [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team. - See the [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team.
- Want to try it before doing anything else? Do it [online](https://try.gogs.io/unknwon/gogs) or go down to the **Installation -> Install from binary** section! - Want to try it before doing anything else? Do it [online](https://try.gogs.io/unknwon/gogs) or go down to the **Installation -> Install from binary** section!
- Having trouble? Get help with [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.md). - Having trouble? Get help with [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.md).
- Want to help with localization? Check out [Crowdin](https://crowdin.com/project/gogs)! - Want to help with localization? Check out the [guide](http://gogs.io/docs/features/i18n.html)!
## Features ## Features
@ -52,7 +52,7 @@ The goal of this project is to make the easiest, fastest, and most painless way
- Drone CI integration - Drone CI integration
- Supports MySQL, PostgreSQL and SQLite3 - Supports MySQL, PostgreSQL and SQLite3
- Social account login (GitHub, Google, QQ, Weibo) - Social account login (GitHub, Google, QQ, Weibo)
- Multi-language support ([10 languages](https://crowdin.com/project/gogs)) - Multi-language support ([11 languages](https://crowdin.com/project/gogs))
## System Requirements ## System Requirements

8
README_ZH.md

@ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个基于 Go 语言的自助 Git 服务。
![Demo](http://gogs.qiniudn.com/gogs_demo.gif) ![Demo](http://gogs.qiniudn.com/gogs_demo.gif)
##### 当前版本:0.5.16 Beta ##### 当前版本:0.6.0 Beta
## 开发目的 ## 开发目的
@ -13,11 +13,11 @@ 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/unknwon/gogs) 或查看 **安装部署 -> 二进制安装** 小节。 - 想要先睹为快?通过 [在线体验](https://try.gogs.io/unknwon/gogs) 或查看 **安装部署 -> 二进制安装** 小节。
- 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.md) 页面获取帮助。 - 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.md) 页面获取帮助。
- 希望帮助多国语言界面的翻译吗?请立即访问 [Crowdin](https://crowdin.com/project/gogs)! - 希望帮助多国语言界面的翻译吗?请立即访问 [详情页面](http://gogs.io/docs/features/i18n.html)!
## 功能特性 ## 功能特性
@ -39,7 +39,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
- Drone CI 持续部署集成 - Drone CI 持续部署集成
- 支持 MySQL、PostgreSQL 以及 SQLite3 数据库 - 支持 MySQL、PostgreSQL 以及 SQLite3 数据库
- 社交帐号登录(GitHub、Google、QQ、微博) - 社交帐号登录(GitHub、Google、QQ、微博)
- 多语言支持([10 种语言]([more](https://crowdin.com/project/gogs))) - 多语言支持([11 种语言]([more](https://crowdin.com/project/gogs)))
## 系统要求 ## 系统要求

2
cmd/serve.go

@ -128,7 +128,7 @@ func runServ(c *cli.Context) {
repo, err := models.GetRepositoryByName(repoUser.Id, repoName) repo, err := models.GetRepositoryByName(repoUser.Id, repoName)
if err != nil { if err != nil {
if err == models.ErrRepoNotExist { if models.IsErrRepoNotExist(err) {
if user.Id == repoUser.Id || repoUser.IsOwnedBy(user.Id) { if user.Id == repoUser.Id || repoUser.IsOwnedBy(user.Id) {
fail("Repository does not exist", "Repository does not exist: %s/%s", repoUser.Name, repoName) fail("Repository does not exist", "Repository does not exist: %s/%s", repoUser.Name, repoName)
} else { } else {

20
cmd/web.go

@ -34,6 +34,7 @@ import (
"github.com/gogits/gogs/modules/auth/apiv1" "github.com/gogits/gogs/modules/auth/apiv1"
"github.com/gogits/gogs/modules/avatar" "github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/bindata"
"github.com/gogits/gogs/modules/git" "github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/middleware" "github.com/gogits/gogs/modules/middleware"
@ -78,11 +79,11 @@ func checkVersion() {
// Check dependency version. // Check dependency version.
checkers := []VerChecker{ checkers := []VerChecker{
{"github.com/Unknwon/macaron", macaron.Version, "0.5.1"}, {"github.com/Unknwon/macaron", macaron.Version, "0.5.4"},
{"github.com/macaron-contrib/binding", binding.Version, "0.0.5"}, {"github.com/macaron-contrib/binding", binding.Version, "0.0.6"},
{"github.com/macaron-contrib/cache", cache.Version, "0.0.7"}, {"github.com/macaron-contrib/cache", cache.Version, "0.0.7"},
{"github.com/macaron-contrib/csrf", csrf.Version, "0.0.3"}, {"github.com/macaron-contrib/csrf", csrf.Version, "0.0.3"},
{"github.com/macaron-contrib/i18n", i18n.Version, "0.0.5"}, {"github.com/macaron-contrib/i18n", i18n.Version, "0.0.7"},
{"github.com/macaron-contrib/session", session.Version, "0.1.6"}, {"github.com/macaron-contrib/session", session.Version, "0.1.6"},
{"gopkg.in/ini.v1", ini.Version, "1.2.0"}, {"gopkg.in/ini.v1", ini.Version, "1.2.0"},
} }
@ -123,9 +124,18 @@ func newMacaron() *macaron.Macaron {
Funcs: []template.FuncMap{base.TemplateFuncs}, Funcs: []template.FuncMap{base.TemplateFuncs},
IndentJSON: macaron.Env != macaron.PROD, IndentJSON: macaron.Env != macaron.PROD,
})) }))
localeNames, err := bindata.AssetDir("conf/locale")
if err != nil {
log.Fatal(4, "Fail to list locale files: %v", err)
}
localFiles := make(map[string][]byte)
for _, name := range localeNames {
localFiles[name] = bindata.MustAsset("conf/locale/" + name)
}
m.Use(i18n.I18n(i18n.Options{ m.Use(i18n.I18n(i18n.Options{
SubURL: setting.AppSubUrl, SubURL: setting.AppSubUrl,
Directory: path.Join(setting.ConfRootPath, "locale"), Files: localFiles,
CustomDirectory: path.Join(setting.CustomPath, "conf/locale"), CustomDirectory: path.Join(setting.CustomPath, "conf/locale"),
Langs: setting.Langs, Langs: setting.Langs,
Names: setting.Names, Names: setting.Names,
@ -457,7 +467,7 @@ func runWeb(ctx *cli.Context) {
// robots.txt // robots.txt
m.Get("/robots.txt", func(ctx *middleware.Context) { m.Get("/robots.txt", func(ctx *middleware.Context) {
if setting.HasRobotsTxt { if setting.HasRobotsTxt {
ctx.ServeFile(path.Join(setting.CustomPath, "robots.txt")) ctx.ServeFileContent(path.Join(setting.CustomPath, "robots.txt"))
} else { } else {
ctx.Error(404) ctx.Error(404)
} }

7
conf/README

@ -0,0 +1,7 @@
Execute following command in ROOT directory when anything is changed:
$ go-bindata -o=modules/bindata/bindata.go -ignore="\\.DS_Store|README" -pkg=bindata conf/...
Add -debug flag to make life easier in development(somehow isn't working):
$ go-bindata -debug -o=modules/bindata/bindata.go -ignore="\\.DS_Store|README" -pkg=bindata conf/...

6
conf/app.ini

@ -82,7 +82,7 @@ ENABLE_CACHE_AVATAR = false
ENABLE_NOTIFY_MAIL = false ENABLE_NOTIFY_MAIL = false
; More detail: https://github.com/gogits/gogs/issues/165 ; More detail: https://github.com/gogits/gogs/issues/165
ENABLE_REVERSE_PROXY_AUTHENTICATION = false ENABLE_REVERSE_PROXY_AUTHENTICATION = false
ENABLE_REVERSE_PROXY_AUTO_REGISTERATION = false ENABLE_REVERSE_PROXY_AUTO_REGISTRATION = false
[webhook] [webhook]
; Cron task interval in minutes ; Cron task interval in minutes
@ -286,5 +286,5 @@ INTERVAL = 24
ARGS = ARGS =
[i18n] [i18n]
LANGS = en-US,zh-CN,zh-HK,de-DE,fr-CA,nl-NL,lv-LV,ru-RU,ja-JP,es-ES LANGS = en-US,zh-CN,zh-HK,de-DE,fr-CA,nl-NL,lv-LV,ru-RU,ja-JP,es-ES,pt-BR
NAMES = English,简体中文,繁體中文,Deutsch,Français,Nederlands,Latviešu,Русский,日本语,Español NAMES = English,简体中文,繁體中文,Deutsch,Français,Nederlands,Latviešu,Русский,日本语,Español,Português

BIN
conf/content/git-bare.zip

Binary file not shown.

3
conf/locale/TRANSLATORS

@ -7,4 +7,5 @@ Huimin Wang <wanghm2009@hotmail.co.jp>
Thomas Fanninger <gogs.thomas@fanninger.at> Thomas Fanninger <gogs.thomas@fanninger.at>
Łukasz Jan Niemier <lukasz@niemier.pl> Łukasz Jan Niemier <lukasz@niemier.pl>
Lafriks <lafriks@gmail.com> Lafriks <lafriks@gmail.com>
Miguel de la Cruz <miguel@mcrx.me> Miguel de la Cruz <miguel@mcrx.me>
Natan Albuquerque <natanalbuquerque5@gmail.com>

21
conf/locale/locale_de-DE.ini

@ -281,13 +281,13 @@ init_readme=Repository mit README.md 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)
goget_meta=Go-Get Meta
goget_meta_helper=Dieses Repository wird man mit <span class="label label-blue label-radius">go get</span> klonen können.
need_auth=Authorisierung benötigt need_auth=Authorisierung benötigt
migrate_type=Migrationstyp migrate_type=Migrationstyp
migrate_type_helper=Dieses Repository wird ein <span class="label label-blue label-radius">Spiegel</span> migrate_type_helper=Dieses Repository wird ein <span class="label label-blue label-radius">Spiegel</span>
migrate_repo=Repository migrieren migrate_repo=Repository migrieren
migrate.clone_address=Adresse kopieren
migrate.invalid_local_path=Lokaler Pfad ist ungültig, er existiert nicht oder ist kein Ordner.
copy_link=Kopieren copy_link=Kopieren
click_to_copy=In Zwischenablage kopieren click_to_copy=In Zwischenablage kopieren
@ -595,7 +595,10 @@ auths.domain=Domain
auths.host=Host auths.host=Host
auths.port=Port auths.port=Port
auths.base_dn=Base DN auths.base_dn=Base DN
auths.attributes=Suchattribute auths.attribute_username=Benutzername Attribut
auths.attribute_name=Vorname Attribut
auths.attribute_surname=Nachname Attribut
auths.attribute_mail=E-Mail Attribut
auths.filter=Suchfilter auths.filter=Suchfilter
auths.ms_ad_sa=Ms Ad SA auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=SMTP-Authentifizierungstyp auths.smtp_auth=SMTP-Authentifizierungstyp
@ -693,12 +696,12 @@ notices.op=Op.
notices.delete_success=System-Mitteilung erfolgreich gelöscht. notices.delete_success=System-Mitteilung erfolgreich gelöscht.
[action] [action]
create_repo=hat Repository <a href="%s/%s">%s</a> erstellt create_repo=hat Repository <a href="%s">%s</a> erstellt
commit_repo=hat nach <a href="%s/%s/src/%s">%s</a> in <a href="%s/%s">%s</a> gepusht commit_repo=hat nach <a href="%s/src/%s">%[2]s</a> in <a href="%[1]s">%[3]s</a> gepusht
create_issue=`hat Issue <a href="%s/issues/%s">%[1]s#%[2]s</a> eröffnet` create_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> eröffnet`
comment_issue=`hat Issue <a href="%s/issues/%s">%[1]s#%[2]s</a> kommentiert` comment_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> kommentiert`
transfer_repo=hat Repository <code>%s</code> transferiert an <a href="/%s%s">%s</a> transfer_repo=hat Repository <code>%s</code> transferiert an <a href="%s">%s</a>
push_tag=hat nach <a href="%s/%s/src/%s">%s</a> in <a href="%s/%s">%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_2_commits=Zeige Vergleich dieser 2 Commits compare_2_commits=Zeige Vergleich dieser 2 Commits
[tool] [tool]

93
conf/locale/locale_en-US.ini

@ -114,13 +114,13 @@ remember_me = Remember Me
forgot_password= Forgot Password forgot_password= Forgot Password
forget_password = Forgot password? forget_password = Forgot password?
sign_up_now = Need an account? Sign up now. sign_up_now = Need an account? Sign up now.
confirmation_mail_sent_prompt = A new confirmation e-mail has been sent to <b>%s</b>, please check your inbox within the next %d hours to complete your registration. confirmation_mail_sent_prompt = A new confirmation e-mail has been sent to <b>%s</b>, please check your inbox within the next %d hours to complete the registration process.
sign_in_email = Sign in to your e-mail sign_in_email = Sign in to your e-mail
active_your_account = Activate Your Account active_your_account = Activate Your Account
resent_limit_prompt = Sorry, you are sending an activation e-mail too frequently. Please wait 3 minutes. resent_limit_prompt = Sorry, you already requested an activation email recently. Please wait 3 minutes then try again.
has_unconfirmed_mail = Hi %s, you have an unconfirmed e-mail address (<b>%s</b>). If you haven't received a confirmation e-mail or need to resend a new one, please click on the button below. has_unconfirmed_mail = Hi %s, you have an unconfirmed e-mail address (<b>%s</b>). If you haven't received a confirmation e-mail or need to resend a new one, please click on the button below.
resend_mail = Click here to resend your activation e-mail resend_mail = Click here to resend your activation e-mail
email_not_associate = This e-mail address does not associate to any account. email_not_associate = This e-mail address is not associated with any account.
send_reset_mail = Click here to (re)send your password reset e-mail send_reset_mail = Click here to (re)send your password reset e-mail
reset_password = Reset Your Password reset_password = Reset Your Password
invalid_code = Sorry, your confirmation code has expired or not valid. invalid_code = Sorry, your confirmation code has expired or not valid.
@ -162,23 +162,23 @@ illegal_repo_name = Repository name contains illegal characters.
illegal_org_name = Organization name contains illegal characters. illegal_org_name = Organization name contains illegal characters.
illegal_team_name = Team name contains illegal characters. illegal_team_name = Team name contains illegal characters.
username_password_incorrect = Username or password is not correct. username_password_incorrect = Username or password is not correct.
enterred_invalid_repo_name = Please make sure you entered repository name is correct. enterred_invalid_repo_name = Please make sure that the repository name you entered is correct.
enterred_invalid_owner_name = Please make sure you entered owner name is correct. enterred_invalid_owner_name = Please make sure that the owner name you entered is correct.
enterred_invalid_password = Please make sure you entered password is correct. enterred_invalid_password = Please make sure the that password you entered is correct.
user_not_exist = Given user does not exist. user_not_exist = Given user does not exist.
last_org_owner = The user to remove is the last member in owner team. There must be another owner. last_org_owner = Removing the last user from a owner team isn't allowed, as there must always be at least one owner in any given organization.
invalid_ssh_key = Sorry, we're not able to verify your SSH key: %s invalid_ssh_key = Sorry, we're not able to verify your SSH key: %s
unable_verify_ssh_key = Gogs cannot verify your SSH key, but we assume that is valid, please make sure yourself. unable_verify_ssh_key = Gogs cannot verify your SSH key, but we assume that it is valid, please double-check it.
auth_failed = Authentication failed: %v auth_failed = Authentication failed: %v
still_own_repo = Your account still have ownership of repository, you have to delete or transfer them first. still_own_repo = Your account still has ownership over at least one repository, you have to delete or transfer them first.
still_has_org = Your account still have membership of organization, you have to left or delete them first. still_has_org = Your account still has membership in at least one organization, you have to leave or delete your memberships first.
org_still_own_repo = This organization still have ownership of repository, you have to delete or transfer them first. org_still_own_repo = This organization still have ownership of repository, you have to delete or transfer them first.
still_own_user = This authentication still has used by some users, you should move them and then delete again. still_own_user = This authentication still is in use by at least one user, please remove them from the authentication and try again.
target_branch_not_exist = Target branch does not exist target_branch_not_exist = Target branch does not exist.
[user] [user]
change_avatar = Change your avatar at gravatar.com change_avatar = Change your avatar at gravatar.com
@ -208,7 +208,7 @@ location = Location
update_profile = Update Profile update_profile = Update Profile
update_profile_success = Your profile has been updated successfully. update_profile_success = Your profile has been updated successfully.
change_username = Username Changed change_username = Username Changed
change_username_desc = Username has been changed, do you want to continue? This will affect all links relate to your account. change_username_desc = You changed your username. This will affect the way how links relate to your account. Do you want to continue?
continue = Continue continue = Continue
cancel = Cancel cancel = Cancel
@ -224,7 +224,7 @@ change_password = Change Password
old_password = Current Password old_password = Current Password
new_password = New Password new_password = New Password
password_incorrect = Current password is not correct. password_incorrect = Current password is not correct.
change_password_success = Password is changed successfully. You can now sign in via new password. change_password_success = Your password was successfully changed. You can now sign using this new password.
emails = E-mail Addresses emails = E-mail Addresses
manage_emails = Manage e-mail addresses manage_emails = Manage e-mail addresses
@ -234,12 +234,13 @@ primary_email = Set as primary
delete_email = Delete delete_email = Delete
add_new_email = Add new e-mail address add_new_email = Add new e-mail address
add_email = Add e-mail add_email = Add e-mail
add_email_confirmation_sent = A new confirmation e-mail has been sent to <b>%s</b>, please check your inbox within the next %d hours to complete the confirmation process.
add_email_success = Your new E-mail address was successfully added. add_email_success = Your new E-mail address was successfully added.
manage_ssh_keys = Manage SSH Keys manage_ssh_keys = Manage SSH Keys
add_key = Add Key add_key = Add Key
ssh_desc = This is a list of SSH keys associated with your account. Remove any keys that you do not recognize. ssh_desc = This is a list of SSH keys associated with your account. As these keys allow anyone using them to gain access to your repositories, it is highly important that you make sure you recognize them.
ssh_helper = <strong>Need help?</strong> Check out our guide to <a href="%s">generating SSH keys</a> or troubleshoot <a href="%s">common SSH Problems</a>. ssh_helper = <strong>Don't know how?</strong> Check out GitHub's guide to <a href="%s">create your own SSH keys</a> or solve <a href="%s">common problems</a> you might encounter using SSH.
add_new_key = Add SSH Key add_new_key = Add SSH Key
key_name = Key Name key_name = Key Name
key_content = Content key_content = Content
@ -257,12 +258,12 @@ unbind_success = Social account has been unbound.
manage_access_token = Manage Personal Access Tokens manage_access_token = Manage Personal Access Tokens
generate_new_token = Generate New Token generate_new_token = Generate New Token
tokens_desc = Tokens you have generated that can be used to access the Gogs API. tokens_desc = Tokens you have generated that can be used to access the Gogs API.
new_token_desc = As for now, every token will have full access to your account. new_token_desc = Each token will have full access to your account.
token_name = Token Name token_name = Token Name
generate_token = Generate Token generate_token = Generate Token
generate_token_succees = New access token has been generated successfully! Make sure to copy your new personal access token now. You won't be able to see it again! generate_token_succees = Your access token was successfully generated! Make sure to copy it right now, as you won't be able to see it again later!
delete_token = Delete delete_token = Delete
delete_token_success = Personal access token has been deleted successfully! Don't forget to update your applications as well. delete_token_success = This personal access token has been successfully removed successfully! Don't forget to update your applications as well.
delete_account = Delete Your Account delete_account = Delete Your Account
delete_prompt = The operation will delete your account permanently, and <strong>CANNOT</strong> be undone! delete_prompt = The operation will delete your account permanently, and <strong>CANNOT</strong> be undone!
@ -273,12 +274,12 @@ delete_account_desc = This account is going to be deleted permanently, do you wa
[repo] [repo]
owner = Owner owner = Owner
repo_name = Repository Name repo_name = Repository Name
repo_name_helper = Great repository names are short, memorable and <strong>unique</strong>. repo_name_helper = A good repository name is usually composed of short, memorable and unique keywords.
visibility = Visibility visibility = Visibility
visiblity_helper = This repository is <span class="label label-red label-radius">Private</span> visiblity_helper = This repository is <span class="label label-red label-radius">Private</span>
fork_repo = Fork Repository fork_repo = Fork Repository
fork_from = Fork From fork_from = Fork From
fork_visiblity_helper = Forked repository cannot change its visiblity fork_visiblity_helper = You cannot alter the visibility of a forked repository.
repo_desc = Description repo_desc = Description
repo_lang = Language repo_lang = Language
repo_lang_helper = Select a .gitignore file repo_lang_helper = Select a .gitignore file
@ -291,7 +292,7 @@ mirror_interval = Mirror Interval (hour)
need_auth = Need Authorization need_auth = Need Authorization
migrate_type = Migration Type migrate_type = Migration Type
migrate_type_helper = This repository will be a <span class="label label-blue label-radius">Mirror</span> migrate_type_helper = This repository will be a <span class="label label-blue label-radius">mirror</span>
migrate_repo = Migrate Repository migrate_repo = Migrate Repository
migrate.clone_address = Clone Address migrate.clone_address = Clone Address
migrate.invalid_local_path = Invalid local path, it does not exist or not a directory. migrate.invalid_local_path = Invalid local path, it does not exist or not a directory.
@ -344,13 +345,13 @@ settings.danger_zone = Danger Zone
settings.site = Official Site settings.site = Official Site
settings.update_settings = Update Settings settings.update_settings = Update Settings
settings.change_reponame = Repository Name Changed settings.change_reponame = Repository Name Changed
settings.change_reponame_desc = Repository name has been changed, do you want to continue? This will affect all links relate to this repository. settings.change_reponame_desc = Repository name was changed. This will affect how links relate to the repository. Do you want to continue?
settings.transfer = Transfer Ownership settings.transfer = Transfer Ownership
settings.transfer_desc = Transfer this repo to another user or to an organization where you have admin rights. settings.transfer_desc = Transfer this repository to another user or to an organization in which you have admin rights.
settings.new_owner_has_same_repo = New owner already has a repository with same name. settings.new_owner_has_same_repo = The new owner already has a repository with same name. Please choose another name.
settings.delete = Delete This Repository settings.delete = Delete This Repository
settings.delete_desc = Once you delete a repository, there is no going back. Please be certain. settings.delete_desc = Once you delete a repository, there is no going back. Please be certain.
settings.transfer_notices = <p>- You will lose access if new owner is a individual user.</p><p>- You will remain access if new owner is an organization and you're one of the owners.</p> settings.transfer_notices = <p>- You will lose access if new owner is a individual user.</p><p>- You will conserve access if new owner is an organization and if you're one of the owners.</p>
settings.update_settings_success = Repository options has been updated successfully. settings.update_settings_success = Repository options has been updated successfully.
settings.transfer_owner = New Owner settings.transfer_owner = New Owner
settings.make_transfer = Make Transfer settings.make_transfer = Make Transfer
@ -361,21 +362,21 @@ settings.add_collaborator_success = New collaborator has been added.
settings.remove_collaborator_success = Collaborator has been removed. settings.remove_collaborator_success = Collaborator has been removed.
settings.user_is_org_member = User is organization member who cannot be added as a collaborator. settings.user_is_org_member = User is organization member who cannot be added as a collaborator.
settings.add_webhook = Add Webhook settings.add_webhook = Add Webhook
settings.hooks_desc = Webhooks allow external services to be notified when certain events happen on Gogs. When the specified events happen, we'll send a POST request to each of the URLs you provide. Learn more in our <a target="_blank" href="%s">Webhooks Guide</a>. settings.hooks_desc = Webhooks are much like basic HTTP POST event triggers. Whenever something occurs in Gogs, we will handle the notification to the target host you specify. Learn more in this <a target="_blank" href="%s">Webhooks Guide</a>.
settings.githooks_desc = Git Hooks are powered by Git itself, you can edit files of supported hooks in the list below to apply custom operations. settings.githooks_desc = Git Hooks are powered by Git itself, you can edit files of supported hooks in the list below to perform custom operations.
settings.githook_edit_desc = If hook is not active, sample content will be presented. Leave content to be blank will disable this hook. settings.githook_edit_desc = If the hook is inactive, sample content will be presented. Leaving content to an empty value will disable this hook.
settings.githook_name = Hook Name settings.githook_name = Hook Name
settings.githook_content = Hook Content settings.githook_content = Hook Content
settings.update_githook = Update Hook settings.update_githook = Update Hook
settings.remove_hook_success = Webhook has been removed. settings.remove_hook_success = Webhook has been removed.
settings.add_webhook_desc = We’ll send a <code>POST</code> request to the URL below with details of any subscribed events. You can also specify which data format you'd like to receive (JSON, <code>x-www-form-urlencoded</code>, <em>etc</em>). More information can be found in <a target="_blank" href="%s">Webhooks Guide</a>. settings.add_webhook_desc = Gogs will send a <code>POST</code> request to the URL you specify, along with regarding the event that occured. You can also specify what kind of data format you'd like to get upon triggering the hook (JSON, x-www-form-urlencoded, XML, etc). More information can be found in our <a target="_blank" href="%s">Webhooks Guide</a>.
settings.payload_url = Payload URL settings.payload_url = Payload URL
settings.content_type = Content Type settings.content_type = Content Type
settings.secret = Secret settings.secret = Secret
settings.event_desc = Which events would you like to trigger this webhook? settings.event_desc = Upon which events should this webhook be triggered?
settings.event_push_only = Just the <code>push</code> event. settings.event_push_only = Just the <code>push</code> event.
settings.active = Active settings.active = Active
settings.active_helper = We will deliver event details when this hook is triggered. settings.active_helper = Details regarding the event which triggered the hook will be delivered as well.
settings.add_hook_success = New webhook has been added. settings.add_hook_success = New webhook has been added.
settings.update_webhook = Update Webhook settings.update_webhook = Update Webhook
settings.update_hook_success = Webhook has been updated. settings.update_hook_success = Webhook has been updated.
@ -414,7 +415,7 @@ release.preview = Preview
release.content_placeholder = Write some content release.content_placeholder = Write some content
release.loading = Loading... release.loading = Loading...
release.prerelease_desc = This is a pre-release release.prerelease_desc = This is a pre-release
release.prerelease_helper = We’ll point out that this release is identified as non-production ready. release.prerelease_helper = We’ll point out that this release is not production-ready.
release.publish = Publish Release release.publish = Publish Release
release.save_draft = Save Draft release.save_draft = Save Draft
release.edit_release = Edit Release release.edit_release = Edit Release
@ -446,11 +447,11 @@ settings.website = Website
settings.location = Location settings.location = Location
settings.update_settings = Update Settings settings.update_settings = Update Settings
settings.change_orgname = Organization Name Changed settings.change_orgname = Organization Name Changed
settings.change_orgname_desc = Organization name has been changed, do you want to continue? This will affect all links relate to this organization. settings.change_orgname_desc = Organization name has been changed. This will affect how links relate to the organization. Do you want to continue?
settings.update_setting_success = Organization setting has been updated successfully. settings.update_setting_success = Organization settings were successfully updated.
settings.delete = Delete Organization settings.delete = Delete Organization
settings.delete_account = Delete This Organization settings.delete_account = Delete This Organization
settings.delete_prompt = The operation will delete this organization permanently, and <strong>CANNOT</strong> be undone! settings.delete_prompt = The organization will be permanently removed, and this <strong>CANNOT</strong> be undone!
settings.confirm_delete_account = Confirm Deletion settings.confirm_delete_account = Confirm Deletion
settings.delete_org_title = Organization Deletion settings.delete_org_title = Organization Deletion
settings.delete_org_desc = This organization is going to be deleted permanently, do you want to continue? settings.delete_org_desc = This organization is going to be deleted permanently, do you want to continue?
@ -484,7 +485,7 @@ teams.update_settings = Update Settings
teams.delete_team = Delete This Team teams.delete_team = Delete This Team
teams.add_team_member = Add Team Member teams.add_team_member = Add Team Member
teams.delete_team_title = Team Deletion teams.delete_team_title = Team Deletion
teams.delete_team_desc = This team is going to be deleted, do you want to continue? Members of this team may lose access to some repositories. teams.delete_team_desc = As this team will be deleted, members of this team may lose access to some repositories. Do you want to continue?
teams.delete_team_success = Given team has been deleted successfully. teams.delete_team_success = Given team has been deleted successfully.
teams.read_permission_desc = This team grants <strong>Read</strong> access: members can view and clone the team's repositories. teams.read_permission_desc = This team grants <strong>Read</strong> access: members can view and clone the team's repositories.
teams.write_permission_desc = This team grants <strong>Write</strong> access: members can read from and push to the team's repositories. teams.write_permission_desc = This team grants <strong>Write</strong> access: members can read from and push to the team's repositories.
@ -574,8 +575,8 @@ 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
users.update_profile = Update Account Profile users.update_profile = Update Account Profile
users.delete_account = Delete This Account users.delete_account = Delete This Account
users.still_own_repo = This account still have ownership of repository, you have to delete or transfer them first. users.still_own_repo = This account still has ownership over at least one repository, you have to delete or transfer them first.
users.still_has_org = This account still have membership of organization, you have to left or delete them first. users.still_has_org = This account still has membership in at least one organization, you have to leave or delete the organizations first.
orgs.org_manage_panel = Organization Manage Panel orgs.org_manage_panel = Organization Manage Panel
orgs.name = Name orgs.name = Name
@ -703,12 +704,12 @@ notices.op = Op.
notices.delete_success = System notice has been deleted successfully. notices.delete_success = System notice has been deleted successfully.
[action] [action]
create_repo = created repository <a href="%s/%s">%s</a> create_repo = created repository <a href="%s">%s</a>
commit_repo = pushed to <a href="%s/%s/src/%s">%s</a> at <a href="%s/%s">%s</a> commit_repo = pushed to <a href="%s/src/%s">%[2]s</a> at <a href="%[1]s">%[3]s</a>
create_issue = `opened issue <a href="%s/issues/%s">%[1]s#%[2]s</a>` create_issue = `opened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue = `commented on issue <a href="%s/issues/%s">%[1]s#%[2]s</a>` comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
transfer_repo = transfered repository <code>%s</code> to <a href="/%s%s">%s</a> transfer_repo = transfered repository <code>%s</code> to <a href="%s">%s</a>
push_tag = pushed tag <a href="%s/%s/src/%s">%s</a> to <a href="%s/%s">%s</a> push_tag = pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
compare_2_commits = View comparison for these 2 commits compare_2_commits = View comparison for these 2 commits
[tool] [tool]

21
conf/locale/locale_es-ES.ini

@ -281,13 +281,13 @@ init_readme=Crear este repositorio con un fichero README.md
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)
goget_meta=Go-Get Meta
goget_meta_helper=Este repositorio será <span class="label label-blue label-radius">Go-Getable</span>
need_auth=Requiere Autorización need_auth=Requiere Autorización
migrate_type=Tipo de Migración migrate_type=Tipo de Migración
migrate_type_helper=Este repositorio será un <span class="label label-blue label-radius">Mirror</span> migrate_type_helper=Este repositorio será un <span class="label label-blue label-radius">Mirror</span>
migrate_repo=Migrar Repositorio migrate_repo=Migrar Repositorio
migrate.clone_address=Clonar Dirección
migrate.invalid_local_path=Rutal local inválida, no existe o no es un directorio.
copy_link=Copiar copy_link=Copiar
click_to_copy=Copiar al portapapeles click_to_copy=Copiar al portapapeles
@ -595,7 +595,10 @@ auths.domain=Dominio
auths.host=Host auths.host=Host
auths.port=Puerto auths.port=Puerto
auths.base_dn=Base DN auths.base_dn=Base DN
auths.attributes=Atributos de búsqueda auths.attribute_username=Atributo username
auths.attribute_name=Atributo nombre
auths.attribute_surname=Atributo apellido
auths.attribute_mail=Atributo correo electrónico
auths.filter=Filtro de Búsqueda auths.filter=Filtro de Búsqueda
auths.ms_ad_sa=Ms Ad SA auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=Tipo de Autorización SMTP auths.smtp_auth=Tipo de Autorización SMTP
@ -693,12 +696,12 @@ notices.op=Op.
notices.delete_success=La notificación del sistema se ha eliminado correctamente. notices.delete_success=La notificación del sistema se ha eliminado correctamente.
[action] [action]
create_repo=Repositorio creado <a href="%s/%s">%s</a> create_repo=Repositorio creado <a href="%s">%s</a>
commit_repo=hizo push a <a href="%s/%s/src/%s">%s</a> en <a href="%s/%s">%s</a> commit_repo=hizo push a <a href="%s/src/%s">%[2]s</a> en <a href="%[1]s">%[3]s</a>
create_issue=`incidencia abierta <a href="%s/issues/%s">%[1]s#%[2]s</a>` create_issue=`incidencia abierta <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`comentó en la incidencia <a href="%s/issues/%s">%[1]s#%[2]s</a>` comment_issue=`comentó en la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
transfer_repo=transfirió el repositorio <code>%s</code> a <a href="/%s%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/%s/src/%s">%s</a> a <a href="%s/%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>
compare_2_commits=Ver la comparación de estos 2 commits compare_2_commits=Ver la comparación de estos 2 commits
[tool] [tool]

21
conf/locale/locale_fr-CA.ini

@ -281,13 +281,13 @@ init_readme=Initialiser ce Référentiel avec un README.md
create_repo=Créer un Référentiel create_repo=Créer un Référentiel
default_branch=Branche par défaut default_branch=Branche par défaut
mirror_interval=Intervalle du miroir (heure) mirror_interval=Intervalle du miroir (heure)
goget_meta=Méta Go-Get
goget_meta_helper=Ce Référentiel sera <span class="label label-blue label-radius">Go-Getable</span>
need_auth=Nécessite une Autorisation need_auth=Nécessite une Autorisation
migrate_type=Type de Migration migrate_type=Type de Migration
migrate_type_helper=Ce Référentiel sera un <span class="label label-blue label-radius">Miroir</span> migrate_type_helper=Ce Référentiel sera un <span class="label label-blue label-radius">Miroir</span>
migrate_repo=Migrer le Référentiel migrate_repo=Migrer le Référentiel
migrate.clone_address=Adresse du clone
migrate.invalid_local_path=Chemin local non valide, non existant ou n'étant pas un dossier.
copy_link=Copier copy_link=Copier
click_to_copy=Copier dans le presse-papier click_to_copy=Copier dans le presse-papier
@ -595,7 +595,10 @@ auths.domain=Domaine
auths.host=Hôte auths.host=Hôte
auths.port=Port auths.port=Port
auths.base_dn=Base DN (Nom Distingué) auths.base_dn=Base DN (Nom Distingué)
auths.attributes=Rechercher les Attributs auths.attribute_username=Attribut du nom d'utilisateur
auths.attribute_name=Attribut du prénom
auths.attribute_surname=Attribut du nom de famille
auths.attribute_mail=Attribut de l'e-mail
auths.filter=Filtre de recherche auths.filter=Filtre de recherche
auths.ms_ad_sa=Ms Ad SA auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=Type d'Autorisation SMTP auths.smtp_auth=Type d'Autorisation SMTP
@ -693,12 +696,12 @@ notices.op=Auteur
notices.delete_success=Note système supprimée avec succès. notices.delete_success=Note système supprimée avec succès.
[action] [action]
create_repo=a crée le Référentiel <a href="%s/%s">%s</a> create_repo=a crée le Référentiel <a href="%s">%s</a>
commit_repo=a soumis à <a href="%s/%s/src/%s">%s</a> chez <a href="%s/%s">%s</a> commit_repo=a soumis à <a href="%s/src/%s">%[2]s</a> chez <a href="%[1]s">%[3]s</a>
create_issue=`a ouvert un problème <a href="%s/issues/%s">%[1]s#%[2]s</a>` create_issue=`a ouvert un problème <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`a commenté le problème <a href="%s/issues/%s">%[1]s#%[2]s</a>` comment_issue=`a commenté le problème <a href="%s/issues/%s">%s#%[2]s</a>`
transfer_repo=a transféré le Référentiel <code>%s</code> à <a href="/%s%s">%s</a> transfer_repo=a transféré le Référentiel <code>%s</code> à <a href="%s">%s</a>
push_tag=a tagé <a href="%s/%s/src/%s">%s</a> à <a href="%s/%s">%s</a> push_tag=a tagé <a href="%s/src/%s">%[2]s</a> à <a href="%[1]s">%[3]s</a>
compare_2_commits=Comparer ces 2 commissions compare_2_commits=Comparer ces 2 commissions
[tool] [tool]

21
conf/locale/locale_ja-JP.ini

@ -281,13 +281,13 @@ init_readme=README.md 付きでリポジトリを初期化
create_repo=リポジトリを作成 create_repo=リポジトリを作成
default_branch=デフォルトのブランチ default_branch=デフォルトのブランチ
mirror_interval=ミラー 間隔(時) mirror_interval=ミラー 間隔(時)
goget_meta=Go-Get メタ
goget_meta_helper=このリポジトリは <span class="label label-blue label-radius"> Go-Getable </span> になります
need_auth=認証が必要 need_auth=認証が必要
migrate_type=マイグレーションの種類 migrate_type=マイグレーションの種類
migrate_type_helper=このリポジトリは <span class="label label-blue label-radius"> ミラー</span> になります migrate_type_helper=このリポジトリは <span class="label label-blue label-radius"> ミラー</span> になります
migrate_repo=リポジトリを移行 migrate_repo=リポジトリを移行
migrate.clone_address=クローンアドレス
migrate.invalid_local_path=ローカルパスが無効です。存在しないかディレクトリではありません。
copy_link=コピー copy_link=コピー
click_to_copy=クリップボードにコピー click_to_copy=クリップボードにコピー
@ -595,7 +595,10 @@ auths.domain=ドメイン
auths.host=ホスト auths.host=ホスト
auths.port=ポート auths.port=ポート
auths.base_dn=ベースのドメイン名 auths.base_dn=ベースのドメイン名
auths.attributes=属性検索 auths.attribute_username=ユーザー名属性
auths.attribute_name=名前属性
auths.attribute_surname=名字属性
auths.attribute_mail=Eメール属性
auths.filter=検索フィルター auths.filter=検索フィルター
auths.ms_ad_sa=Ms Ad SA auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=SMTP 認証の種類 auths.smtp_auth=SMTP 認証の種類
@ -693,12 +696,12 @@ notices.op=Op。
notices.delete_success=システム通知が正常に削除されました。 notices.delete_success=システム通知が正常に削除されました。
[action] [action]
create_repo=リポジトリ <a href="%s/%s"> %s</a>を作成しました create_repo=リポジトリ <a href="%s"> %s</a>を作成しました
commit_repo=<a href="%s/%s">%s</a>を<a href="%s/%s/src/%s">%s</a>にプッシュしました commit_repo=<a href="%[1]s">%[3]s</a>を<a href="%[1]s/src/%[2]s">%[2]s</a>にプッシュしました
create_issue=`問題 <a href="%s/issues/%s">%[1]s#%[2]s</a> を開きました` create_issue=`問題 <a href="%s/issues/%s">%s#%[2]s</a> を開きました`
comment_issue=`問題 <a href="%s/issues/%s">%[1]s#%[2]s</a> のコメント` comment_issue=`問題 <a href="%s/issues/%s">%s#%[2]s</a> のコメント`
transfer_repo=リポジトリ <code>%s</code> を <a href="/%s%s">%s</a> へ転送しました transfer_repo=リポジトリ <code>%s</code> を <a href="%s">%s</a> へ転送しました
push_tag=<a href="%s/%s">%s</a> に タグ <a href="%s/%s/src/%s">%s</a> をプッシュしました push_tag=<a href="%[1]s">%[3]s</a> に タグ <a href="%[1]s/src/%[2]s">%[2]s</a> をプッシュしました
compare_2_commits=これら 2 のコミットの比較を閲覧する compare_2_commits=これら 2 のコミットの比較を閲覧する
[tool] [tool]

21
conf/locale/locale_lv-LV.ini

@ -281,13 +281,13 @@ init_readme=Inicializēt šo repozitoriju ar README.md failu
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)
goget_meta=Go-Get metadati
goget_meta_helper=Šis repozitorijs saturēs <span class="label label-blue label-radius">Go-Get</span> metadatus
need_auth=Nepieciešama autorizācija need_auth=Nepieciešama autorizācija
migrate_type=Migrācijas veids migrate_type=Migrācijas veids
migrate_type_helper=Šis repozitorijs būs <span class="label label-blue label-radius">Spoguļots</span> migrate_type_helper=Šis repozitorijs būs <span class="label label-blue label-radius">Spoguļots</span>
migrate_repo=Migrēt repozitoriju migrate_repo=Migrēt repozitoriju
migrate.clone_address=Clone Address
migrate.invalid_local_path=Invalid local path, it does not exist or not a directory.
copy_link=Kopēt copy_link=Kopēt
click_to_copy=Kopēt uz starpliktuvi click_to_copy=Kopēt uz starpliktuvi
@ -595,7 +595,10 @@ auths.domain=Domēns
auths.host=Resursdators auths.host=Resursdators
auths.port=Ports auths.port=Ports
auths.base_dn=Pamata DN auths.base_dn=Pamata DN
auths.attributes=Meklēšanas atribūti auths.attribute_username=Username attribute
auths.attribute_name=First name attribute
auths.attribute_surname=Surname attribute
auths.attribute_mail=E-mail attribute
auths.filter=Meklēšanas filtrs auths.filter=Meklēšanas filtrs
auths.ms_ad_sa=MS Ad SA auths.ms_ad_sa=MS Ad SA
auths.smtp_auth=SMTP autorizācijas veids auths.smtp_auth=SMTP autorizācijas veids
@ -693,12 +696,12 @@ notices.op=Op.
notices.delete_success=Sistēmas paziņojums tika veiksmīgi izdzēsts. notices.delete_success=Sistēmas paziņojums tika veiksmīgi izdzēsts.
[action] [action]
create_repo=izveidoja repozitoriju <a href="%s/%s">%s</a> create_repo=izveidoja repozitoriju <a href="%s">%s</a>
commit_repo=veica izmaiņu nosūtīšanu atzaram <a href="%s/%s/src/%s">%s</a> repozitorijā <a href="%s/%s">%s</a> commit_repo=veica izmaiņu nosūtīšanu atzaram <a href="%s/src/%s">%[2]s</a> repozitorijā <a href="%[1]s">%[3]s</a>
create_issue=`reģistrēja problēmu <a href="%s/issues/%s">%[1]s#%[2]s</a>` create_issue=`reģistrēja problēmu <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`pievienoja komentāru problēmai <a href="%s/issues/%s">%[1]s#%[2]s</a>` comment_issue=`pievienoja komentāru problēmai <a href="%s/issues/%s">%s#%[2]s</a>`
transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="/%s%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/%s/src/%s">%s</a> repozitorijam <a href="%s/%s">%s</a> push_tag=pievienoja tagu <a href="%s/src/%s">%[2]s</a> repozitorijam <a href="%[1]s">%[3]s</a>
compare_2_commits=Veikt salīdzināšanu starp šīm 2 revīzijām compare_2_commits=Veikt salīdzināšanu starp šīm 2 revīzijām
[tool] [tool]

21
conf/locale/locale_nl-NL.ini

@ -281,13 +281,13 @@ init_readme=Initialiseer deze repositorie met een README.md
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)
goget_meta=Go-Get Meta
goget_meta_helper=Deze repositorie is nu beschikbaar voor <span class="label label-blue label-radius">Go-Get</span>
need_auth=Autorisatie vereist need_auth=Autorisatie vereist
migrate_type=Migratie type migrate_type=Migratie type
migrate_type_helper=Deze repositorie zal een <span class="label label-blue label-radius">mirror</span> worden migrate_type_helper=Deze repositorie zal een <span class="label label-blue label-radius">mirror</span> worden
migrate_repo=Migreer repositorie migrate_repo=Migreer repositorie
migrate.clone_address=Clone Address
migrate.invalid_local_path=Invalid local path, it does not exist or not a directory.
copy_link=Kopieer copy_link=Kopieer
click_to_copy=Kopieer link naar plakbord click_to_copy=Kopieer link naar plakbord
@ -595,7 +595,10 @@ auths.domain=Domein
auths.host=Host auths.host=Host
auths.port=Poort auths.port=Poort
auths.base_dn=Base DN auths.base_dn=Base DN
auths.attributes=Zoek attributen auths.attribute_username=Username attribute
auths.attribute_name=First name attribute
auths.attribute_surname=Surname attribute
auths.attribute_mail=E-mail attribute
auths.filter=Zoek filter auths.filter=Zoek filter
auths.ms_ad_sa=MS Ad SA auths.ms_ad_sa=MS Ad SA
auths.smtp_auth=SMTP authenticatietype auths.smtp_auth=SMTP authenticatietype
@ -693,12 +696,12 @@ notices.op=Op.
notices.delete_success=Systeem bericht is met succes verwijderd. notices.delete_success=Systeem bericht is met succes verwijderd.
[action] [action]
create_repo=repositorie aangemaakt in <a href="%s/%s">%s</a> create_repo=repositorie aangemaakt in <a href="%s">%s</a>
commit_repo=push update naar <a href="%s/%s/src/%s">%s</a> in <a href="%s/%s">%s</a commit_repo=push update naar <a href="%s/src/%s">%[2]s</a> in <a href="%[1]s">%[3]s</a>
create_issue=`opende issue in <a href="%s/issues/%s">%[1]s#%[2]s</a>` create_issue=`opende issue in <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`reactie op issue <a href="%s/issues/%s">%[1]s#%[2]s</a>` comment_issue=`reactie op issue <a href="%s/issues/%s">%s#%[2]s</a>`
transfer_repo=repositorie verplaatst naar <code>%s</code> naar <a href="/%s%s">%s</a> transfer_repo=repositorie verplaatst naar <code>%s</code> naar <a href="%s">%s</a>
push_tag=geduwd label <a href="%s/%s/src/%s"> %s</a> naar <a href="%s/%s"> %s</a> push_tag=geduwd label <a href="%s/src/%s"> %[2]s</a> naar <a href="%[1]s"> %[3]s</a>
compare_2_commits=Weergave vergelijking voor deze 2 commits compare_2_commits=Weergave vergelijking voor deze 2 commits
[tool] [tool]

727
conf/locale/locale_pt-BR.ini

@ -0,0 +1,727 @@
app_desc=Um serviço de Git auto-hospedado e amigável escrito em Go
home=Página Inicial
dashboard=Painel de controle
explore=Explorar
help=Ajuda
sign_in=Entrar
social_sign_in=Entrada Social: 2ª etapa <small>associar uma conta</small>
sign_out=Sair
sign_up=Cadastrar
register=Registrar
website=Site
version=Versão
page=Página
template=Modelo
language=Idioma
username=Usuário
email=E-mail
password=Senha
re_type=Redigite
captcha=Captcha
repository=Repositório
organization=Organização
mirror=Espelho
new_repo=Novo Repositório
new_migrate=Nova Migração
new_fork=Novo Fork de Repositório
new_org=Nova Organização
manage_org=Gerenciar Organizações
admin_panel=Painel do Administrador
account_settings=Configurações da Conta
settings=Configurações
news_feed=Feed de Notícias
pull_requests=Solicitações de Pull
issues=Problemas
cancel=Cancelar
[install]
install=Instalação
title=Etapas de instalação para Primeira Execução
requite_db_desc=Gogs requer MySQL, PostgreSQL ou SQLite3.
db_type=Tipo do Banco de Dados
host=Host
user=Usuário
password=Senha
db_name=Nome do Banco de Dados
db_helper=Por favor, use o mecanismo INNODB com o conjunto de caracteres utf8_general_ci para MySQL.
ssl_mode=Modo SSL
path=Caminho
sqlite_helper=O caminho do arquivo do banco de dados do SQLite3.
general_title=Configurações Gerais do Gogs
repo_path=Caminho da Raiz do Repositório
repo_path_helper=Todos os repositórios remotos do Git serão salvos neste diretório.
run_user=Executar Usuário
run_user_helper=O usuário deve ter acesso ao caminho raiz do repositório e executar o Gogs
domain=Domínio
domain_helper=Isto afeta URLs para clonagem via SSH.
http_port=Porta HTTP
http_port_helper=Número da porta em que a aplicação irá executar.
app_url=URL do Aplicativo
app_url_helper=Isto afeta a URL de clonagem via HTTP/HTTPs e também o email.
email_title=Configurações do Serviço de E-mail(Opcionais)
smtp_host=Host SMTP
mailer_user=E-mail do Remetente
mailer_password=Senha do Remetente
notify_title=Configurações de Notificação (Opcional)
register_confirm=Habilitar Confirmação de Registro
mail_notify=Habilitar Notificação de Correio
admin_title=Configurações da Conta de Administrador
admin_name=Nome de Usuário
admin_password=Senha
confirm_password=Confirmar Senha
admin_email=E-mail
install_gogs=Instalar Gogs
test_git_failed=Falha ao testar o comando 'git': %v
sqlite3_not_available=Sua versão não suporta SQLite3, por favor faça o download da versão binária oficial em %s, NÃO da versão gobuild.
invalid_db_setting=Configuração do banco de dados não está correta: %v
invalid_repo_path=A raiz do repositório é inválida: %v
run_user_not_match=O usuário da execução não é o usuário atual: %s -> %s
save_config_failed=Falha ao salvar a configuração: %v
invalid_admin_setting=Configuração da conta de administrador está inválida: %v
install_success=Bem-vindo! Estamos contentes que você escolheu o Gogs, divirta-se e tenha cuidado.
[home]
uname_holder=Nome de Usuário ou E-mail
password_holder=Senha
switch_dashboard_context=Trocar Contexto do Painel de Controle
my_repos=Meus Repositórios
collaborative_repos=Repositórios Colaborativos
my_orgs=Minhas Organizações
my_mirrors=Meus Espelhos
[explore]
repos=Repositórios
[auth]
create_new_account=Criar Nova Conta
register_hepler_msg=Já tem uma conta? Entre agora!
social_register_hepler_msg=Já tem uma conta? Junte-se agora!
disable_register_prompt=Desculpe, novos registros estão desabilitados. Por favor entre em contato com o administrador do site.
disable_register_mail=Desculpe, a confirmação de registro por email foi desabilitada.
remember_me=Lembrar de Mim
forgot_password=Esqueci a Senha
forget_password=Esqueceu a senha?
sign_up_now=Precisa de uma conta? Cadastre-se agora.
confirmation_mail_sent_prompt=Um novo e-mail de confirmação foi enviado para <b>%s</b>, por favor, verifique sua caixa de entrada nas próximas %d horas para completar seu registro.
sign_in_email=Entre com seu e-mail
active_your_account=Ativar Sua Conta
resent_limit_prompt=Desculpe, você está enviando um e-mail de ativação com muita frequência. Por favor, aguarde 3 minutos.
has_unconfirmed_mail=Oi %s, você possui um endereço de e-mail não confirmado (<b>%s</b>). Se você não recebeu um e-mail de confirmação ou precisa reenviar um novo, clique no botão abaixo.
resend_mail=Clique aqui para reenviar seu e-mail de ativação
email_not_associate=Este endereço de e-mail não é associado à nenhuma conta.
send_reset_mail=Clique aqui para (re)enviar seu e-mail de redefinição da senha
reset_password=Redefinir Sua Senha
invalid_code=Desculpe, seu código de confirmação expirou ou não é válido.
reset_password_helper=Clique aqui para redefinir sua senha
password_too_short=O comprimento da senha não pode ser menor que 6.
[form]
UserName=Nome de usuário
RepoName=Nome do repositório
Email=Endereço de e-mail
Password=Senha
Retype=Redigite a senha
SSHTitle=Nome da chave SSH
HttpsUrl=URL HTTPS
PayloadUrl=URL de carga
TeamName=Nome da equipe
AuthName=Nome de autorização
AdminEmail=E-mail do Administrador
require_error=` não pode estar vazio.`
alpha_dash_error=` devem ser caracteres alfanuméricos ou hífen (-) ou sublinhado (_).`
alpha_dash_dot_error=` devem ser caracteres alfanuméricos ou hífen (-) ou sublinhado (_).`
min_size_error=` deve conter pelo menos %s caracteres.`
max_size_error=` deve conter no máximo %s caracteres.`
email_error=` não é um endereço de e-mail válido.`
url_error=`não é uma URL válida.`
unknown_error=Erro desconhecido:
captcha_incorrect=O captcha não correspondeu.
password_not_match=Senha e confirmar senha não são as mesmas.
username_been_taken=Nome de usuário já foi tomado.
repo_name_been_taken=Nome do repositório já foi tomado.
org_name_been_taken=Nome da organização já foi tomado.
team_name_been_taken=Nome da equipe já foi tomado.
email_been_used=Endereço de e-mail já foi usado.
ssh_key_been_used=Nome da chave pública foi usado.
illegal_username=Seu nome de usuário contém caracteres ilegais.
illegal_repo_name=Nome do repositório contém caracteres ilegais.
illegal_org_name=Nome da organização contém caracteres ilegais.
illegal_team_name=O nome da equipe contém caracteres ilegais.
username_password_incorrect=Usuário ou senha incorretos.
enterred_invalid_repo_name=Por favor certifique-se que informou o nome do repositório corretamente.
enterred_invalid_owner_name=Por favor, verifique se o nome do proprietário está correto.
enterred_invalid_password=Por favor, verifique se a senha que você digitou está correta.
user_not_exist=O usuário dado não existe.
last_org_owner=O usuário a ser removido é o último membro na equipe de proprietários. Deve haver um outro proprietário.
invalid_ssh_key=Desculpe, não conseguimos verificar a sua chave SSH: %s
unable_verify_ssh_key=Gogs não pode verificar sua chave SSH, mas assumimos que é válida, por favor, verifique a chave pessoalmente.
auth_failed=A autenticação falhou: %v
still_own_repo=Sua conta ainda tem propriedade do repositório, você tem que excluir ou transferí-la primeiro.
still_has_org=Sua conta ainda faz parte da organização, você deve sair ou excluí-la primeiro.
org_still_own_repo=Esta organização ainda tem a propriedade do repositório, você deve excluir ou transferí-la primeiro.
still_own_user=Esta autenticação ainda é usada por alguns usuários, você deve movê-los e depois apagar novamente.
target_branch_not_exist=O ramo de destino não existe.
[user]
change_avatar=Altere o seu avatar em gravatar.com
change_custom_avatar=Altere seu avatar nas configurações
join_on=Inscreveu-se em
repositories=Repositórios
activity=Atividade Pública
followers=Seguidores
starred=Marcado
following=Seguindo
[settings]
profile=Perfil
password=Senha
ssh_keys=Chaves SSH
social=Contas Sociais
applications=Aplicativos
orgs=Organizações
delete=Deletar Conta
uid=Uid
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.
full_name=Nome Completo
website=Site
location=Localização
update_profile=Atualizar o Perfil
update_profile_success=O seu perfil foi atualizado com sucesso.
change_username=Nome de Usuário Alterado
change_username_desc=O nome de usuário foi alterado, você quer continuar? Isto afetará todos os links relacionados à sua conta.
continue=Continuar
cancel=Cancelar
enable_custom_avatar=Habilitar Avatar Customizado
enable_custom_avatar_helper=Habilite para desativar a busca no Gravatar
choose_new_avatar=Escolha um novo avatar
update_avatar=Atualizar configuração de Avatar
uploaded_avatar_not_a_image=O arquivo enviado não é uma imagem.
no_custom_avatar_available=Nenhum avatar personalizado disponível, não pode habilitá-lo.
update_avatar_success=Sua configuração de avatar foi atualizada com sucesso.
change_password=Alterar a Senha
old_password=Senha Atual
new_password=Nova Senha
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.
emails=Endereços de E-mail
manage_emails=Gerenciar endereços de e-mail
email_desc=Seu endereço de email principal será usado para notificações e outras operações.
primary=Principal
primary_email=Definir como principal
delete_email=Deletar
add_new_email=Adicionar novo endereço de e-mail
add_email=Adicionar e-mail
add_email_success=Seu novo endereço de E-mail foi adicionado com sucesso.
manage_ssh_keys=Gerenciar Chaves SSH
add_key=Adicionar Chave
ssh_desc=Esta é uma lista de chaves SSH associadas com a sua conta. Remova quaisquer chaves que você não reconheça.
ssh_helper=<strong>Precisa de ajuda?</strong> Confira nosso guia para <a href="%s">gerar chaves SSH</a> ou solucionar <a href="%s">problemas comuns com SSH</a>.
add_new_key=Adicionar Chave SSH
key_name=Nome da Chave
key_content=Conteúdo
add_key_success=Nova Chave SSH foi adicionada!
delete_key=Deletar
add_on=Adicionado em
last_used=Última vez usado em
no_activity=Nenhuma atividade recente
manage_social=Gerenciar Contas Sociais Associadas
social_desc=Esta é uma lista de contas sociais. Remova qualquer ligação que você não reconheça.
unbind=Desvincular
unbind_success=A conta social foi desvinculada.
manage_access_token=Gerenciar Tokens de Acesso pessoais
generate_new_token=Gerar novo Token
tokens_desc=Tokens gerados por você que podem ser usados para acessar a API Gogs.
new_token_desc=Por enquanto, todo token terá acesso completo à sua conta.
token_name=Nome do Token
generate_token=Gerar Token
generate_token_succees=Novo token de acesso gerado com sucesso! Certifique-se de copiar seu novo token de acesso pessoal agora. Você não poderá vê-lo novamente!
delete_token=Excluir
delete_token_success=Token de acesso pessoal deletado com sucesso! Não esqueça-se de atualizar seus aplicativos também.
delete_account=Deletar Sua Conta
delete_prompt=A operação deletará sua conta permanentemente, e <strong>NÃO PODERÁ</strong> ser desfeita!
confirm_delete_account=Confirmar Deleção
delete_account_title=Deleção da Conta
delete_account_desc=Esta conta será deletada permanentemente, você quer continuar?
[repo]
owner=Dono
repo_name=Nome do Repositório
repo_name_helper=Nomes de repositórios bons são pequenos, memorizáveis e <strong>únicos</strong>.
visibility=Visibilidade
visiblity_helper=Este repositório é <span class="label label-red label-radius">Privado</span>
fork_repo=Fork o Repositório
fork_from=Fork de
fork_visiblity_helper=Não é possível alterar a visibilidade de um repositório bifurcado
repo_desc=Descrição
repo_lang=Idioma
repo_lang_helper=Selecione um arquivo .gitignore
license=Licença
license_helper=Selecione um arquivo de licença
init_readme=Inicialize este repositório com um LEIAME.md
create_repo=Criar Repositório
default_branch=Ramo padrão
mirror_interval=Intervalo de Espelho (hora)
need_auth=Precisa de Autorização
migrate_type=Tipo de Migração
migrate_type_helper=Este repositório será um <span class="label label-blue label-radius">Espelho</span>
migrate_repo=Migrar Repositório
migrate.clone_address=Endereço de Clone
migrate.invalid_local_path=Caminho local inválido, não existe ou não é um diretório.
copy_link=Copiar
click_to_copy=Copiar para a área de transferência
copied=Copiado com sucesso
clone_helper=Precisa de ajuda com a clonagem? Visite a <a target="_blank" href="%s">Ajuda</a>!
unwatch=Deixar de Observar
watch=Observar
unstar=Remover favorito
star=Favorito
fork=Fork
no_desc=Nenhuma Descrição
quick_guide=Guia Rápido
clone_this_repo=Clonar este repositório
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
branch=Ramo
tree=Árvore
branch_and_tags=Ramos & Tags
branches=Ramos
tags=Tags
issues=Problemas
commits=Commits
releases=Lançamentos
file_raw=Cru
file_history=Histórico
file_view_raw=Ver cru
commits.commits=Commits
commits.search=Pesquisar commits
commits.find=Buscar
commits.author=Autor
commits.message=Mensagem
commits.date=Data
commits.older=Mais Antigo
commits.newer=Mais Novo
settings=Configurações
settings.options=Opções
settings.collaboration=Colaboração
settings.hooks=Hooks da web
settings.githooks=Hooks do Git
settings.deploy_keys=Chaves de Deploy
settings.basic_settings=Configurações Básicas
settings.danger_zone=Zona de Perigo
settings.site=Site Oficial
settings.update_settings=Configurações de Atualização
settings.change_reponame=Nome do Repositório Alterado
settings.change_reponame_desc=O nome do repositório foi alterado, você quer continuar? Isto afetará todos os links relacionados à este repositório.
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.new_owner_has_same_repo=O novo dono já tem um repositório com o mesmo nome.
settings.delete=Deletar Este Repositório
settings.delete_desc=Uma vez que você deleta um repositório, não tem volta. Por favor, tenha certeza.
settings.transfer_notices=<p>- Você perderá acesso se o novo dono é um usuário individual.</p><p>- Você permanecerá com o acesso se o novo dono é uma organização e você é um dos donos.</p>
settings.update_settings_success=As opções do repositório foram atualizadas com sucesso.
settings.transfer_owner=Novo Dono
settings.make_transfer=Fazer Transferência
settings.transfer_succeed=A posse do repositório foi transferido com sucesso.
settings.confirm_delete=Confirmar Deleção
settings.add_collaborator=Adicionar um Novo Colaborador
settings.add_collaborator_success=O novo colaborador foi adicionado.
settings.remove_collaborator_success=O colaborador foi removido.
settings.user_is_org_member=O usuário é um membro da organização que não pode ser adicionado como um colaborador.
settings.add_webhook=Adicionar Webhook
settings.hooks_desc=Hooks da web ou Webhooks permitem serviços externos serem notificados quando certos eventos acontecem no Gogs. Quando acontecem os eventos especificados, enviaremos uma solicitação POST para cada uma das URLs que você fornecer. Saiba mais no nosso <a target="_blank" href="%s"> Guia de Webhooks</a>.
settings.githooks_desc=Hooks do Git são ofertados pelo próprio Git, você pode editar arquivos de hooks suportados na lista abaixo para aplicar operações personalizadas.
settings.githook_edit_desc=Se o hook não estiver ativo, o conteúdo de exemplo será apresentado. Deixar o conteúdo em branco irá desativar esse hook.
settings.githook_name=Nome do Hook
settings.githook_content=Conteúdo do Hook
settings.update_githook=Atualizar Hook
settings.remove_hook_success=O hook da web foi removido.
settings.add_webhook_desc=Enviaremos uma solicitação <code>POST</code> para o URL abaixo com detalhes de quaisquer eventos inscritos. Você pode também especificar qual formato de dados você gostaria de receber (JSON, <code>x-www-form-urlencoded</code>, <em>etc</em>). Mais informação pode ser encontrada em <a target="_blank" href="%s">Webhooks Guide</a>.
settings.payload_url=URL de carga
settings.content_type=Tipo de Conteúdo
settings.secret=Secreto
settings.event_desc=Quais eventos você gostaria de acionar a esse hook da web?
settings.event_push_only=Apenas o evento <code>push</code>.
settings.active=Ativar
settings.active_helper=Enviaremos detalhes do evento quando este hook for acionado.
settings.add_hook_success=Novos hooks de web foram adicionados.
settings.update_webhook=Atualizar Hook da Web
settings.update_hook_success=Hook da web atualizado.
settings.delete_webhook=Excluir Hook da Web
settings.recent_deliveries=Entregas Recentes
settings.hook_type=Tipo de Hook
settings.add_slack_hook_desc=Adicionar <a href="%s">Slack</a> de integração para o seu repositório.
settings.slack_token=Token
settings.slack_domain=Domínio
settings.slack_channel=Canal
diff.browse_source=Ver Fontes
diff.parent=pai
diff.commit=commit
diff.data_not_available=Dados Diff não disponíveis.
diff.show_diff_stats=Mostrar estatísticas do Diff
diff.stats_desc=<strong> %d arquivos alterados</strong> com <strong>%d adições</strong> e <strong>%d exclusões</strong>
diff.bin=BIN
diff.view_file=Ver Arquivo
release.releases=Lançamentos
release.new_release=Novo Lançamento
release.draft=Rascunho
release.prerelease=Pré-Lançamento
release.stable=Estável
release.edit=editar
release.ahead=<strong>%d</strong> commits para %s depois desta versão
release.source_code=Código-fonte
release.tag_name=Nome da tag
release.target=Destino
release.tag_helper=Escolha uma tag existente, ou crie uma nova tag em publicar.
release.release_title=Título da Versão
release.content_with_md=Conteúdo com <a href="%s">Markdown</a>
release.write=Escrever
release.preview=Visualizar
release.content_placeholder=Escreva algum conteúdo
release.loading=Carregando...
release.prerelease_desc=Esta é uma versão prévia
release.prerelease_helper=Vou salientar que esta versão é identificada como não pronta para produção.
release.publish=Publicar Versão
release.save_draft=Salvar Rascunho
release.edit_release=Editar Versão
release.tag_name_already_exist=Já existiu versão com esse nome de tag.
[org]
org_name_holder=Nome da Organização
org_name_helper=Nomes de grandes organizações são curtos e memoráveis.
org_email_helper=O E-mail da organização receberá todas as notificações e as confirmações.
create_org=Criar Organização
repo_updated=Atualizado
people=Pessoas
invite_someone=Convidar Alguém
teams=Equipes
lower_members=membros
lower_repositories=repositórios
create_new_team=Criar Nova Equipe
org_desc=Descrição
team_name=Nome da Equipe
team_desc=Descrição
team_name_helper=Você usará este nome para mencionar esta equipe em conversas.
team_desc_helper=Do que trata essa equipe?
team_permission_desc=Que nível de permissão esta equipe deve ter?
settings=Configurações
settings.options=Opções
settings.full_name=Nome Completo
settings.website=Site
settings.location=Localização
settings.update_settings=Atualizar Configurações
settings.change_orgname=Nome da Organização Alterado
settings.change_orgname_desc=O nome da organização foi alterado, você quer continuar? Isto afetará todos os links que se relacionam a esta organização.
settings.update_setting_success=Configuração da organização atualizada com sucesso.
settings.delete=Deletar Organização
settings.delete_account=Deletar Esta Organização
settings.delete_prompt=A operação deletará esta organização permanentemente, e <strong>NÃO PODERÁ</strong> ser desfeita!
settings.confirm_delete_account=Confirmar Deleção
settings.delete_org_title=Deleção da Organização
settings.delete_org_desc=Esta organização será deletada permanentemente, você quer continuar?
settings.hooks_desc=Adicionar Hooks da Web que serão acionados para <strong>todos os repositórios</strong> dessa organização.
members.public=Público
members.public_helper=tornar privado
members.private=Privado
members.private_helper=torar público
members.owner=Dono
members.member=Membro
members.conceal=Ocultar
members.remove=Remover
members.leave=Sair
members.invite_desc=Comece digitando um nome de usuário para convidá-lo como novo membro para %s:
members.invite_now=Convidar Agora
teams.join=Juntar-se
teams.leave=Deixar
teams.read_access=Acesso de Leitura
teams.read_access_helper=Esta equipe poderá ver e clonar os repositórios dela.
teams.write_access=Acesso de Escrita
teams.write_access_helper=Esta equipa será capaz de ler os seus repositórios, bem como fazer push para eles.
teams.admin_access=Acesso do Administrador
teams.admin_access_helper=Esta equipe será capaz de fazer push/pull em seus repositórios, bem como adicionar-lhes outros colaboradores.
teams.no_desc=Esta equipe não tem descrição
teams.settings=Configurações
teams.owners_permission_desc=Donos tem acesso total a <strong>todos repositórios</strong> e também <strong>direitos de administrador</strong> para a organização.
teams.members=Membros da Equipe
teams.update_settings=Atualizar Configurações
teams.delete_team=Deletar Esta Equipe
teams.add_team_member=Adicionar Membro da Equipe
teams.delete_team_title=Deleção da Equipe
teams.delete_team_desc=Este equipe será deletada, você quer continuar? Membros desta equipe poderão perder acesso a alguns repositórios.
teams.delete_team_success=A equipe dada foi deletada com sucesso.
teams.read_permission_desc=Essa equipe concede acesso para <strong>Leitura</strong>: membros podem ver e clonar os repositórios da equipe.
teams.write_permission_desc=Esta equipe concede acesso para <strong>escrita</strong>: Membros podem ler e fazer push para os repositórios da equipe.
teams.admin_permission_desc=Esta equipe concede acesso de <strong>Administrador</strong>: Membros podem ler, fazer push e adicionar outros colaboradores para os repositórios da equipe.
teams.repositories=Repositórios da Equipe
teams.add_team_repository=Adicionar Repositório da Equipe
teams.remove_repo=Remover
teams.add_nonexistent_repo=O repositório que você está tentando adicionar não existe, por favor, crie-o primeiro.
[admin]
dashboard=Painel de controle
users=Usuários
organizations=Organizações
repositories=Repositórios
authentication=Autenticações
config=Configuração
notices=Sistema de notificações
monitor=Monitoramento
prev=Anterior
next=Próximo
dashboard.statistic=Estatística
dashboard.operations=Operações
dashboard.system_status=Status do Monitor de Sistema
dashboard.statistic_info=O banco de dados do Gogs contém <b>%d</b> usuários, <b>%d</b> organizações, <b>%d</b> chaves públicas, <b>%d</b> repositórios, <b>%d</b> observadores, <b>%d</b> estrelas, <b>%d</b> ações, <b>%d</b> acessos, <b>%d</b> questões, <b>%d</b> comentários, <b>%d</b> contas sociais, <b>%d</b> seguidores, <b>%d</b> espelhos, <b>%d</b> versões, <b>%d</b> origens de login, <b>%d</b> Hooks da Web, <b>%d</b> milestones, <b>%d</b> labels, <b>%d</b> tarefas hook, <b>%d</b> equipes, <b>%d</b> tarefas de atualização, <b>%d</b> anexos.
dashboard.operation_name=Nome da Operação
dashboard.operation_switch=Trocar
dashboard.operation_run=Executar
dashboard.clean_unbind_oauth=Limpar OAuthes não acoplados
dashboard.clean_unbind_oauth_success=Todos OAuthes desvinculados foram excluídos com sucesso.
dashboard.delete_inactivate_accounts=Excluir todas as contas inativas
dashboard.delete_inactivate_accounts_success=Todas as contas inativas foram excluídas com sucesso.
dashboard.delete_repo_archives=Excluir todos os arquivos dos repositórios
dashboard.delete_repo_archives_success=Todos os arquivos dos repositórios foram excluídos com sucesso.
dashboard.git_gc_repos=Fazer coleta de lixo nos repositórios
dashboard.git_gc_repos_success=Em todos repositórios, a coleta de lixo foi realizada com sucesso.
dashboard.resync_all_sshkeys=Reescrever o arquivo '.ssh/autorized_key' (atenção: chaves que não sejam do Gogs serão perdidas)
dashboard.resync_all_sshkeys_success=Todas as chaves públicas foram reescritas com sucesso.
dashboard.resync_all_update_hooks=Reescrever todos os hooks de atualização dos repositórios (necessário quando o caminho de configuração customizado é alterado)
dashboard.resync_all_update_hooks_success=Os hooks de atualização de todos os repositórios foram reescritos com sucesso.
dashboard.server_uptime=Servidor Ligado
dashboard.current_goroutine=Goroutines Atuais
dashboard.current_memory_usage=Uso de Memória Atual
dashboard.total_memory_allocated=Total de Memória Alocada
dashboard.memory_obtained=Memória Obtida
dashboard.pointer_lookup_times=Nº de Consultas a Ponteiros
dashboard.memory_allocate_times=Nº de Alocações de Memória
dashboard.memory_free_times=Nº de Liberações de Memória
dashboard.current_heap_usage=Uso Atual da Heap
dashboard.heap_memory_obtained=Memória de Heap Obtida
dashboard.heap_memory_idle=Memória da Heap Ociosa
dashboard.heap_memory_in_use=Memória da Heap em Uso
dashboard.heap_memory_released=Memória da Heap Liberada
dashboard.heap_objects=Objetos na Heap
dashboard.bootstrap_stack_usage=Uso de Pilha Bootstrap
dashboard.stack_memory_obtained=Memória de Pilha Obtida
dashboard.mspan_structures_usage=Uso de Estruturas de MSpan
dashboard.mspan_structures_obtained=Estruturas de MSpan Obtidas
dashboard.mcache_structures_usage=Uso de Estruturas de MCache
dashboard.mcache_structures_obtained=Estruturas de MCache Obtidas
dashboard.profiling_bucket_hash_table_obtained=Perfil Obtido da Bucket Hash Table
dashboard.gc_metadata_obtained=Metadados do GC Obtidos
dashboard.other_system_allocation_obtained=Outra Alocação de Sistema Obtida
dashboard.next_gc_recycle=Próxima Reciclagem do GC
dashboard.last_gc_time=Desde da Última Vez do GC
dashboard.total_gc_time=Pausa Total do GC
dashboard.total_gc_pause=Pausa Total do GC
dashboard.last_gc_pause=Última Pausa do GC
dashboard.gc_times=Nº Execuções do GC
users.user_manage_panel=Painel de Gerenciamento do Usuário
users.new_account=Criar Nova Conta
users.name=Nome
users.activated=Ativado
users.admin=Administrador
users.repos=Repos
users.created=Criado
users.edit=Editar
users.auth_source=Fonte de Autorização
users.local=Local
users.auth_login_name=Nome de Autorização de Login
users.update_profile_success=O perfil da conta foi atualizado com sucesso.
users.edit_account=Editar Conta
users.is_activated=Esta conta está ativada
users.is_admin=Esta conta tem permissões de administrador
users.allow_git_hook=Esta conta tem permissões para criar ganchos Git
users.update_profile=Atualizar Perfil da Conta
users.delete_account=Deletar Esta Conta
users.still_own_repo=Sua conta ainda é proprietária do repositório, você tem que excluir ou transferi-lo primeiro.
users.still_has_org=Sua conta ainda faz parte da organização, você deve sair ou excluí-la primeiro.
orgs.org_manage_panel=Painel de Gerenciamento da Organização
orgs.name=Nome
orgs.teams=Equipes
orgs.members=Membros
repos.repo_manage_panel=Painel de Gerenciamento do Repositório
repos.owner=Dono
repos.name=Nome
repos.private=Privado
repos.watches=Observadores
repos.stars=Estrelas
repos.issues=Problemas
auths.auth_manage_panel=Painel de Gerenciamento da Autorização
auths.new=Adicionar Nova Fonte de Autorização
auths.name=Nome
auths.type=Tipo
auths.enabled=Habilitado
auths.updated=Atualizado
auths.auth_type=Tipo da Autorização
auths.auth_name=Nome da Autorização
auths.domain=Domínio
auths.host=Host
auths.port=Porta
auths.base_dn=Base DN
auths.attribute_username=Atributo nome de usuário
auths.attribute_name=Atributo primeiro nome
auths.attribute_surname=Atributo sobrenome
auths.attribute_mail=Atributo e-mail
auths.filter=Filtro de Pesquisa
auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=Tipo de Autorização de SMTP
auths.smtphost=Host SMTP
auths.smtpport=Porta SMTP
auths.enable_tls=Habilitar Criptografia TLS
auths.enable_auto_register=Habilitar Registro Automático
auths.tips=Dicas
auths.edit=Editar Configuração da Autorização
auths.activated=Esta autenticação foi ativada
auths.update_success=A configuração da autorização foi atualizada com sucesso.
auths.update=Atualizar Configuração da Autorização
auths.delete=Excluir Esta Autorização
auths.delete_auth_title=Exclusão da Autorização
auths.delete_auth_desc=Esta autorização será excluída, deseja continuar?
config.server_config=Configuração do Servidor
config.app_name=Nome do Aplicativo
config.app_ver=Versão do Aplicativo
config.app_url=URL do Aplicativo
config.domain=Domínio
config.offline_mode=Modo Offline
config.disable_router_log=Desabilitar o Log do Roteador
config.run_user=Usuário de Execução
config.run_mode=Modo de Execução
config.repo_root_path=Caminho Raiz do Repositório
config.static_file_root_path=Caminho Raiz para Arquivo Estático
config.log_file_root_path=Caminho Raiz para Arquivo de Log
config.script_type=Tipo de Script
config.reverse_auth_user=Usuário de Autenticação Reversa
config.db_config=Configuração do Banco de Dados
config.db_type=Tipo
config.db_host=Host
config.db_name=Nome
config.db_user=Usuário
config.db_ssl_mode=Modo SSL
config.db_ssl_mode_helper=(apenas para "postgres")
config.db_path=Caminho
config.db_path_helper=(apenas para "sqlite3")
config.service_config=Configuração do Serviço
config.register_email_confirm=Requerer Confirmação de E-mail
config.disable_register=Desabilitar Registro
config.show_registration_button=Mostrar Botão de Registo
config.require_sign_in_view=Requerer Entrar no Gogs para Ver
config.mail_notify=Notificação de Correio
config.enable_cache_avatar=Habilitar Cache de Avatar
config.active_code_lives=Ativar Code Lives
config.reset_password_code_lives=Redefinir Senha de Code Lives
config.webhook_config=Configuração de Hook da Web
config.task_interval=Intervalo da Tarefa
config.deliver_timeout=Intervalo de Entrega
config.skip_tls_verify=Pular Verificar TLS
config.mailer_config=Configuração de Correio
config.mailer_enabled=Habilitado
config.mailer_name=Nome
config.mailer_host=Host
config.mailer_user=Usuário
config.oauth_config=Configuração do OAuth
config.oauth_enabled=Habilitado
config.cache_config=Configuração de Cache
config.cache_adapter=Adaptador de Cache
config.cache_interval=Intervalo de Cache
config.cache_conn=Conexão de Cache
config.session_config=Configuração da Sessão
config.session_provider=Provedor da Sessão
config.provider_config=Configuração do Provedor
config.cookie_name=Nome do Cookie
config.enable_set_cookie=Habilitar Uso de Cookie
config.gc_interval_time=Tempo de Intervalo do GC
config.session_life_time=Tempo de Vida da Sessão
config.https_only=Apenas HTTPS
config.cookie_life_time=Tempo de Vida do Cookie
config.picture_config=Configuração da Imagem
config.picture_service=Serviço de Imagens
config.disable_gravatar=Desativar Gravatar
config.log_config=Configuração de Log
config.log_mode=Modo do Log
monitor.cron=Tarefas Cron
monitor.name=Nome
monitor.schedule=Cronograma
monitor.next=Próxima Vez
monitor.previous=Última Vez
monitor.execute_times=Nº de Execuções
monitor.process=Processos em Execução
monitor.desc=Descrição
monitor.start=Hora de Início
monitor.execute_time=Tempo de Execução
notices.system_notice_list=Sistema de Notificações
notices.type=Tipo
notices.type_1=Repositório
notices.desc=Descrição
notices.op=Op.
notices.delete_success=Aviso do sistema foi deletado com sucesso.
[action]
create_repo=repositório criado <a href="%s"> %s</a>
commit_repo=pushed para <a href="%s/src/%s">%[2]s</a> em <a href="%[1]s">%[3]s</a>
create_issue='questão aberta <a href="%s/issues/%s">%s#%[2]s</a>'
comment_issue='comentou sobre a questão <a href="%s/issues/%s">%s#%[2]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>
compare_2_commits=Ver comparação desses 2 commits
[tool]
ago=atrás
from_now=a partir de agora
now=agora
1s=1 segundo %s
1m=1 minuto %s
1h=1 hora %s
1d=1 dia %s
1w=1 semana %s
1mon=1 mês %s
1y=1 ano %s
seconds=%d segundos %s
minutes=%d minutos %s
hours=%d horas %s
days=%d dias %s
weeks=%d semanas %s
months=%d meses %s
years=%d anos %s
raw_seconds=segundos
raw_minutes=minutos

27
conf/locale/locale_ru-RU.ini

@ -281,13 +281,13 @@ init_readme=Создать репозиторий с файлом README.md
create_repo=Создание репозитория create_repo=Создание репозитория
default_branch=Ветка по умолчанию default_branch=Ветка по умолчанию
mirror_interval=Интервал зеркалирования (час) mirror_interval=Интервал зеркалирования (час)
goget_meta=Meta-тег для go get
goget_meta_helper=Репозиторий будет доступен для <span class="label label-blue label-radius">go get</span>
need_auth=Требуется авторизация need_auth=Требуется авторизация
migrate_type=Тип миграции migrate_type=Тип миграции
migrate_type_helper=Этот репозиторий будет <span class="label label-blue label-radius">зеркалом</span> migrate_type_helper=Этот репозиторий будет <span class="label label-blue label-radius">зеркалом</span>
migrate_repo=Перенос репозитория migrate_repo=Перенос репозитория
migrate.clone_address=Скопировать адрес
migrate.invalid_local_path=Недопустимый локальный путь. Возможно он не существует или является не папкой.
copy_link=Копировать copy_link=Копировать
click_to_copy=Скопировать в буфер обмена click_to_copy=Скопировать в буфер обмена
@ -343,18 +343,18 @@ 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=<p>- You will lose access if new owner is a individual user.</p><p>- You will remain access if new owner is an organization and you're one of the owners.</p> settings.transfer_notices=<p>- Вы потеряете доступ, если новый владелец является индивидуальным пользователем.</p><p>- У Вас останется доступ, если новый владелец является организацией, и вы один из её владельцев.</p>
settings.update_settings_success=Настройка репозитория обновлена успешно. settings.update_settings_success=Настройка репозитория обновлена успешно.
settings.transfer_owner=Новый владелец settings.transfer_owner=Новый владелец
settings.make_transfer=Выполнить передачу settings.make_transfer=Выполнить передачу
settings.transfer_succeed=Repository ownership has been transferred successfully. settings.transfer_succeed=Владение репозиторием было успешно передано.
settings.confirm_delete=Подтвердить удаление 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.user_is_org_member=Пользователь является членом организации, члены которой не могут быть добавлены в качестве соавтора. settings.user_is_org_member=Пользователь является членом организации, члены которой не могут быть добавлены в качестве соавтора.
settings.add_webhook=Добавить Webhook settings.add_webhook=Добавить Webhook
settings.hooks_desc=Webhooks allow external services to be notified when certain events happen on Gogs. When the specified events happen, we'll send a POST request to each of the URLs you provide. Learn more in our <a target="_blank" href="%s">Webhooks Guide</a>. settings.hooks_desc=Webhooks позволяют внешним службам получать уведомления при возникновении определенных событий на Gogs. При возникновении указанных событий мы отправим запрос POST на каждый заданный вами URL. Узнать больше можно в нашем <a target="_blank" href="%s">Руководстве по Webhooks</a>.
settings.githooks_desc=Git Hooks are powered by Git itself, you can edit files of supported hooks in the list below to apply custom operations. settings.githooks_desc=Git Hooks are powered by Git itself, you can edit files of supported hooks in the list below to apply custom operations.
settings.githook_edit_desc=If hook is not active, sample content will be presented. Leave content to be blank will disable this hook. settings.githook_edit_desc=If hook is not active, sample content will be presented. Leave content to be blank will disable this hook.
settings.githook_name=Название Hook'a settings.githook_name=Название Hook'a
@ -595,7 +595,10 @@ auths.domain=Домен
auths.host=Хост auths.host=Хост
auths.port=Порт auths.port=Порт
auths.base_dn=Base DN auths.base_dn=Base DN
auths.attributes=Search Attributes auths.attribute_username=Username attribute
auths.attribute_name=First name attribute
auths.attribute_surname=Surname attribute
auths.attribute_mail=E-mail attribute
auths.filter=Фильтр поиска auths.filter=Фильтр поиска
auths.ms_ad_sa=Ms Ad SA auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=Тип авторизации SMTP auths.smtp_auth=Тип авторизации SMTP
@ -693,12 +696,12 @@ notices.op=Op.
notices.delete_success=Системное уведомление успешно удалено. notices.delete_success=Системное уведомление успешно удалено.
[action] [action]
create_repo=создан репозиторий <a href="%s/%s"> %s</a> create_repo=создан репозиторий <a href="%s"> %s</a>
commit_repo=pushed to <a href="%s/%s/src/%s">%s</a> at <a href="%s/%s">%s</a> commit_repo=pushed to <a href="%s/src/%s">%[2]s</a> at <a href="%[1]s">%[3]s</a>
create_issue=`opened issue <a href="%s/issues/%s">%[1]s#%[2]s</a>` create_issue=`opened issue <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`commented on issue <a href="%s/issues/%s">%[1]s#%[2]s</a>` comment_issue=`commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
transfer_repo=transfered repository <code>%s</code> to <a href="/%s%s">%s</a> transfer_repo=transfered repository <code>%s</code> to <a href="%s">%s</a>
push_tag=pushed tag <a href="%s/%s/src/%s">%s</a> to <a href="%s/%s">%s</a> push_tag=pushed tag <a href="%s/src/%s">%[2]s</a> to <a href="%[1]s">%[3]s</a>
compare_2_commits=Просмотреть сравнение двух коммитов compare_2_commits=Просмотреть сравнение двух коммитов
[tool] [tool]

21
conf/locale/locale_zh-CN.ini

@ -281,13 +281,13 @@ init_readme=使用 README.md 文件初始化仓库
create_repo=创建仓库 create_repo=创建仓库
default_branch=默认分支 default_branch=默认分支
mirror_interval=镜像同步周期(小时) mirror_interval=镜像同步周期(小时)
goget_meta=Go-Get 支持
goget_meta_helper=本仓库将可以通过 <span class="label label-blue label-radius">Go Get</span> 获取
need_auth=需要授权验证 need_auth=需要授权验证
migrate_type=迁移类型 migrate_type=迁移类型
migrate_type_helper=本仓库将是 <span class="label label-blue label-radius">镜像</span> migrate_type_helper=本仓库将是 <span class="label label-blue label-radius">镜像</span>
migrate_repo=迁移仓库 migrate_repo=迁移仓库
migrate.clone_address=克隆地址
migrate.invalid_local_path=无效的本地路径,不存在或不是一个目录!
copy_link=复制链接 copy_link=复制链接
click_to_copy=复制到剪切板 click_to_copy=复制到剪切板
@ -595,7 +595,10 @@ auths.domain=域名
auths.host=主机地址 auths.host=主机地址
auths.port=主机端口 auths.port=主机端口
auths.base_dn=Base DN auths.base_dn=Base DN
auths.attributes=Search Attributes auths.attribute_username=用户名属性
auths.attribute_name=名字属性
auths.attribute_surname=姓氏属性
auths.attribute_mail=邮箱属性
auths.filter=Search Filter auths.filter=Search Filter
auths.ms_ad_sa=Ms Ad SA auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=SMTP 授权类型 auths.smtp_auth=SMTP 授权类型
@ -693,12 +696,12 @@ notices.op=操作
notices.delete_success=系统提示删除成功! notices.delete_success=系统提示删除成功!
[action] [action]
create_repo=创建了仓库 <a href="%s/%s">%s</a> create_repo=创建了仓库 <a href="%s">%s</a>
commit_repo=推送了 <a href="%s/%s/src/%s">%s</a> 分支的代码到 <a href="%s/%s">%s</a> commit_repo=推送了 <a href="%s/src/%s">%[2]s</a> 分支的代码到 <a href="%[1]s">%[3]s</a>
create_issue=`创建了工单 <a href="%s/issues/%s">%[1]s#%[2]s</a>` create_issue=`创建了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`评论了工单 <a href="%s/issues/%s">%[1]s#%[2]s</a>` comment_issue=`评论了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
transfer_repo=将仓库 <code>%s</code> 转移至 <a href="/%s%s">%s</a> transfer_repo=将仓库 <code>%s</code> 转移至 <a href="%s">%s</a>
push_tag=推送了标签 <a href="%s/%s/src/%s">%s</a> 到 <a href="%s/%s">%s</a> push_tag=推送了标签 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_2_commits=查看 2 次提交的内容对比 compare_2_commits=查看 2 次提交的内容对比
[tool] [tool]

27
conf/locale/locale_zh-HK.ini

@ -281,13 +281,13 @@ init_readme=使用 README.md 文件初始化倉庫
create_repo=創建倉庫 create_repo=創建倉庫
default_branch=默認分支 default_branch=默認分支
mirror_interval=鏡像同步周期(小時) mirror_interval=鏡像同步周期(小時)
goget_meta=Go-Get 支持
goget_meta_helper=本倉庫將可以通過 <span class="label label-blue label-radius">Go Get</span> 獲取
need_auth=需要授權驗證 need_auth=需要授權驗證
migrate_type=遷移類型 migrate_type=遷移類型
migrate_type_helper=本倉庫將是 <span class="label label-blue label-radius">鏡像</span> migrate_type_helper=本倉庫將是 <span class="label label-blue label-radius">鏡像</span>
migrate_repo=遷移倉庫 migrate_repo=遷移倉庫
migrate.clone_address=複製地址
migrate.invalid_local_path=無效的本地路徑,該路徑不存在或不是一個目錄!
copy_link=複製連結 copy_link=複製連結
click_to_copy=複製到剪切簿 click_to_copy=複製到剪切簿
@ -516,8 +516,8 @@ dashboard.git_gc_repos=對倉庫進行垃圾回收
dashboard.git_gc_repos_success=所有倉庫的垃圾回收已成功完成! dashboard.git_gc_repos_success=所有倉庫的垃圾回收已成功完成!
dashboard.resync_all_sshkeys=重新生成 '.ssh/autorized_key' 文件(警告:不是 Gogs 的密鑰也會被刪除) dashboard.resync_all_sshkeys=重新生成 '.ssh/autorized_key' 文件(警告:不是 Gogs 的密鑰也會被刪除)
dashboard.resync_all_sshkeys_success=所有公鑰重新生成成功! dashboard.resync_all_sshkeys_success=所有公鑰重新生成成功!
dashboard.resync_all_update_hooks=Rewrite all update hook of repositories (needed when custom config path is changed) dashboard.resync_all_update_hooks=重新生成所有倉庫的 Update 鈎子(用於被修改的自定義配置文件)
dashboard.resync_all_update_hooks_success=All repositories' update hook have been rewritten successfully. dashboard.resync_all_update_hooks_success=已成功重新生成所有倉庫的 Update 鈎子!
dashboard.server_uptime=服務執行時間 dashboard.server_uptime=服務執行時間
dashboard.current_goroutine=當前 Goroutines 數量 dashboard.current_goroutine=當前 Goroutines 數量
@ -595,7 +595,10 @@ auths.domain=域名
auths.host=主機地址 auths.host=主機地址
auths.port=主機端口 auths.port=主機端口
auths.base_dn=Base DN auths.base_dn=Base DN
auths.attributes=搜尋屬性 auths.attribute_username=用戶名屬性
auths.attribute_name=名子屬性
auths.attribute_surname=姓氏屬性
auths.attribute_mail=電子郵箱屬性
auths.filter=搜尋過濾 auths.filter=搜尋過濾
auths.ms_ad_sa=Ms Ad SA auths.ms_ad_sa=Ms Ad SA
auths.smtp_auth=SMTP 授權類型 auths.smtp_auth=SMTP 授權類型
@ -647,7 +650,7 @@ config.reset_password_code_lives=重置密碼連結有效期
config.webhook_config=Web 鉤子配置 config.webhook_config=Web 鉤子配置
config.task_interval=任務周期 config.task_interval=任務周期
config.deliver_timeout=推送超時 config.deliver_timeout=推送超時
config.skip_tls_verify=Skip TLS Verify config.skip_tls_verify=忽略 TLS 驗證
config.mailer_config=郵件配置 config.mailer_config=郵件配置
config.mailer_enabled=啟用服務 config.mailer_enabled=啟用服務
config.mailer_name=發送者名稱 config.mailer_name=發送者名稱
@ -693,12 +696,12 @@ notices.op=操作
notices.delete_success=系統提示刪除成功! notices.delete_success=系統提示刪除成功!
[action] [action]
create_repo=創建了倉庫 <a href="%s/%s">%s</a> create_repo=創建了倉庫 <a href="%s">%s</a>
commit_repo=推送了 <a href="%s/%s/src/%s">%s</a> 分支的代碼到 <a href="%s/%s">%s</a> commit_repo=推送了 <a href="%s/src/%s">%[2]s</a> 分支的代碼到 <a href="%[1]s">%[3]s</a>
create_issue=`創建了問題 <a href="%s/issues/%s">%[1]s#%[2]s</a>` create_issue=`創建了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
comment_issue=`評論了問題 <a href="%s/issues/%s">%[1]s#%[2]s</a>` comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
transfer_repo=將倉庫 <code>%s</code> 轉移至 <a href="/%s%s">%s</a> transfer_repo=將倉庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
push_tag=推送了標籤 <a href="%s/%s/src/%s">%s</a> 到 <a href="%s/%s">%s</a> push_tag=推送了標籤 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
compare_2_commits=查看 2 次提交的內容對比 compare_2_commits=查看 2 次提交的內容對比
[tool] [tool]

12
docker-compose.yml

@ -0,0 +1,12 @@
web:
build: .
links:
- mysql
ports:
- "3000:3000"
mysql:
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=gogs
- MYSQL_DATABASE=gogs

2
gogs.go

@ -17,7 +17,7 @@ import (
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
const APP_VER = "0.5.16.0301 Beta" const APP_VER = "0.6.0.0319 Beta"
func init() { func init() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())

6
models/access.go

@ -6,6 +6,8 @@ package models
import ( import (
"fmt" "fmt"
"github.com/gogits/gogs/modules/log"
) )
type AccessMode int type AccessMode int
@ -77,6 +79,10 @@ func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) {
for _, access := range accesses { for _, access := range accesses {
repo, err := GetRepositoryById(access.RepoID) repo, err := GetRepositoryById(access.RepoID)
if err != nil { if err != nil {
if IsErrRepoNotExist(err) {
log.Error(4, "%v", err)
continue
}
return nil, err return nil, err
} }
if err = repo.GetOwner(); err != nil { if err = repo.GetOwner(); err != nil {

86
models/action.go

@ -61,14 +61,14 @@ func init() {
// Action represents user operation type and other information to repository., // Action represents user operation type and other information to repository.,
// it implemented interface base.Actioner so that can be used in template render. // it implemented interface base.Actioner so that can be used in template render.
type Action struct { type Action struct {
Id int64 ID int64 `xorm:"pk autoincr"`
UserId int64 // Receiver user id. UserID int64 // Receiver user id.
OpType ActionType OpType ActionType
ActUserId int64 // Action user id. ActUserID int64 // Action user id.
ActUserName string // Action user name. ActUserName string // Action user name.
ActEmail string ActEmail string
ActAvatar string `xorm:"-"` ActAvatar string `xorm:"-"`
RepoId int64 RepoID int64
RepoUserName string RepoUserName string
RepoName string RepoName string
RefName string RefName string
@ -97,8 +97,15 @@ func (a Action) GetRepoName() string {
return a.RepoName return a.RepoName
} }
func (a Action) GetRepoPath() string {
return path.Join(a.RepoUserName, a.RepoName)
}
func (a Action) GetRepoLink() string { func (a Action) GetRepoLink() string {
return path.Join(setting.AppSubUrl, a.RepoUserName, a.RepoName) if len(setting.AppSubUrl) > 0 {
return path.Join(setting.AppSubUrl, a.GetRepoPath())
}
return "/" + a.GetRepoPath()
} }
func (a Action) GetBranch() string { func (a Action) GetBranch() string {
@ -302,7 +309,7 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
return errors.New("action.CommitRepoAction(GetRepositoryByName): " + err.Error()) return errors.New("action.CommitRepoAction(GetRepositoryByName): " + err.Error())
} }
repo.IsBare = false repo.IsBare = false
if err = UpdateRepository(repo); err != nil { if err = UpdateRepository(repo, false); err != nil {
return errors.New("action.CommitRepoAction(UpdateRepository): " + err.Error()) return errors.New("action.CommitRepoAction(UpdateRepository): " + err.Error())
} }
@ -312,10 +319,18 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
log.Debug("action.CommitRepoAction(updateIssuesCommit): ", err) log.Debug("action.CommitRepoAction(updateIssuesCommit): ", err)
} }
if err = NotifyWatchers(&Action{ActUserId: userId, ActUserName: userName, ActEmail: actEmail, if err = NotifyWatchers(&Action{
OpType: opType, Content: string(bs), RepoId: repoId, RepoUserName: repoUserName, ActUserID: userId,
RepoName: repoName, RefName: refName, ActUserName: userName,
IsPrivate: repo.IsPrivate}); err != nil { ActEmail: actEmail,
OpType: opType,
Content: string(bs),
RepoID: repoId,
RepoUserName: repoUserName,
RepoName: repoName,
RefName: refName,
IsPrivate: repo.IsPrivate,
}); err != nil {
return errors.New("action.CommitRepoAction(NotifyWatchers): " + err.Error()) return errors.New("action.CommitRepoAction(NotifyWatchers): " + err.Error())
} }
@ -402,32 +417,28 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
continue continue
} }
var payload BasePayload
switch w.HookTaskType { switch w.HookTaskType {
case SLACK: case SLACK:
{ s, err := GetSlackPayload(p, w.Meta)
s, err := GetSlackPayload(p, w.Meta) if err != nil {
if err != nil { return errors.New("action.GetSlackPayload: " + err.Error())
return errors.New("action.GetSlackPayload: " + err.Error())
}
CreateHookTask(&HookTask{
Type: w.HookTaskType,
Url: w.Url,
BasePayload: s,
ContentType: w.ContentType,
IsSsl: w.IsSsl,
})
} }
payload = s
default: default:
{ payload = p
p.Secret = w.Secret p.Secret = w.Secret
CreateHookTask(&HookTask{ }
Type: w.HookTaskType,
Url: w.Url, if err = CreateHookTask(&HookTask{
BasePayload: p, Type: w.HookTaskType,
ContentType: w.ContentType, Url: w.Url,
IsSsl: w.IsSsl, BasePayload: payload,
}) ContentType: w.ContentType,
} EventType: HOOK_EVENT_PUSH,
IsSsl: w.IsSsl,
}); err != nil {
return fmt.Errorf("CreateHookTask: %v", err)
} }
} }
@ -436,14 +447,15 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
func newRepoAction(e Engine, u *User, repo *Repository) (err error) { func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
if err = notifyWatchers(e, &Action{ if err = notifyWatchers(e, &Action{
ActUserId: u.Id, ActUserID: u.Id,
ActUserName: u.Name, ActUserName: u.Name,
ActEmail: u.Email, ActEmail: u.Email,
OpType: CREATE_REPO, OpType: CREATE_REPO,
RepoId: repo.Id, RepoID: repo.Id,
RepoUserName: repo.Owner.Name, RepoUserName: repo.Owner.Name,
RepoName: repo.Name, RepoName: repo.Name,
IsPrivate: repo.IsPrivate}); err != nil { IsPrivate: repo.IsPrivate,
}); err != nil {
return fmt.Errorf("notify watchers '%d/%s'", u.Id, repo.Id) return fmt.Errorf("notify watchers '%d/%s'", u.Id, repo.Id)
} }
@ -458,11 +470,11 @@ func NewRepoAction(u *User, repo *Repository) (err error) {
func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repository) (err error) { func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repository) (err error) {
action := &Action{ action := &Action{
ActUserId: actUser.Id, ActUserID: actUser.Id,
ActUserName: actUser.Name, ActUserName: actUser.Name,
ActEmail: actUser.Email, ActEmail: actUser.Email,
OpType: TRANSFER_REPO, OpType: TRANSFER_REPO,
RepoId: repo.Id, RepoID: repo.Id,
RepoUserName: newOwner.Name, RepoUserName: newOwner.Name,
RepoName: repo.Name, RepoName: repo.Name,
IsPrivate: repo.IsPrivate, IsPrivate: repo.IsPrivate,

84
models/error.go

@ -0,0 +1,84 @@
// 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 models
import (
"fmt"
)
// ____ ___
// | | \______ ___________
// | | / ___// __ \_ __ \
// | | /\___ \\ ___/| | \/
// |______//____ >\___ >__|
// \/ \/
type ErrUserOwnRepos struct {
UID int64
}
func IsErrUserOwnRepos(err error) bool {
_, ok := err.(ErrUserOwnRepos)
return ok
}
func (err ErrUserOwnRepos) Error() string {
return fmt.Sprintf("user still has ownership of repositories: [uid: %d]", err.UID)
}
type ErrUserHasOrgs struct {
UID int64
}
func IsErrUserHasOrgs(err error) bool {
_, ok := err.(ErrUserHasOrgs)
return ok
}
func (err ErrUserHasOrgs) Error() string {
return fmt.Sprintf("user still has membership of organizations: [uid: %d]", err.UID)
}
// ________ .__ __ .__
// \_____ \_______ _________ ____ |__|____________ _/ |_|__| ____ ____
// / | \_ __ \/ ___\__ \ / \| \___ /\__ \\ __\ |/ _ \ / \
// / | \ | \/ /_/ > __ \| | \ |/ / / __ \| | | ( <_> ) | \
// \_______ /__| \___ (____ /___| /__/_____ \(____ /__| |__|\____/|___| /
// \/ /_____/ \/ \/ \/ \/ \/
type ErrLastOrgOwner struct {
UID int64
}
func IsErrLastOrgOwner(err error) bool {
_, ok := err.(ErrLastOrgOwner)
return ok
}
func (err ErrLastOrgOwner) Error() string {
return fmt.Sprintf("user is the last member of owner team: [uid: %d]", err.UID)
}
// __________ .__ __
// \______ \ ____ ______ ____ _____|__|/ |_ ___________ ___.__.
// | _// __ \\____ \ / _ \/ ___/ \ __\/ _ \_ __ < | |
// | | \ ___/| |_> > <_> )___ \| || | ( <_> ) | \/\___ |
// |____|_ /\___ > __/ \____/____ >__||__| \____/|__| / ____|
// \/ \/|__| \/ \/
type ErrRepoNotExist struct {
ID int64
UID int64
Name string
}
func IsErrRepoNotExist(err error) bool {
_, ok := err.(ErrRepoNotExist)
return ok
}
func (err ErrRepoNotExist) Error() string {
return fmt.Sprintf("repository does not exist [id: %d, uid: %d, name: %s]", err.ID, err.UID, err.Name)
}

6
models/login.go

@ -215,11 +215,9 @@ func UserSignIn(uname, passwd string) (*User, error) {
switch u.LoginType { switch u.LoginType {
case LDAP: case LDAP:
return LoginUserLdapSource(u, u.LoginName, passwd, return LoginUserLdapSource(u, u.LoginName, passwd, source.Id, source.Cfg.(*LDAPConfig), false)
source.Id, source.Cfg.(*LDAPConfig), false)
case SMTP: case SMTP:
return LoginUserSMTPSource(u, u.LoginName, passwd, return LoginUserSMTPSource(u, u.LoginName, passwd, source.Id, source.Cfg.(*SMTPConfig), false)
source.Id, source.Cfg.(*SMTPConfig), false)
} }
return nil, ErrUnsupportedLoginType return nil, ErrUnsupportedLoginType
} }

5
models/migrations/migrations.go

@ -341,12 +341,15 @@ func teamToTeamRepo(x *xorm.Engine) error {
orgID := com.StrTo(team["org_id"]).MustInt64() orgID := com.StrTo(team["org_id"]).MustInt64()
teamID := com.StrTo(team["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"]), "|") { for _, idStr := range strings.Split(string(team["repo_ids"]), "|") {
repoID := com.StrTo(strings.TrimPrefix(idStr, "$")).MustInt64() repoID := com.StrTo(strings.TrimPrefix(idStr, "$")).MustInt64()
if repoID == 0 { if repoID == 0 || mark[repoID] {
continue continue
} }
mark[repoID] = true
teamRepos = append(teamRepos, &TeamRepo{ teamRepos = append(teamRepos, &TeamRepo{
OrgID: orgID, OrgID: orgID,
TeamID: teamID, TeamID: teamID,

9
models/models.go

@ -89,8 +89,13 @@ func getEngine() (*xorm.Engine, error) {
cnnstr := "" cnnstr := ""
switch DbCfg.Type { switch DbCfg.Type {
case "mysql": case "mysql":
cnnstr = fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8", if DbCfg.Host[0] == '/' { // looks like a unix socket
DbCfg.User, DbCfg.Passwd, DbCfg.Host, DbCfg.Name) cnnstr = fmt.Sprintf("%s:%s@unix(%s)/%s?charset=utf8",
DbCfg.User, DbCfg.Passwd, DbCfg.Host, DbCfg.Name)
} else {
cnnstr = fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8",
DbCfg.User, DbCfg.Passwd, DbCfg.Host, DbCfg.Name)
}
case "postgres": case "postgres":
var host, port = "127.0.0.1", "5432" var host, port = "127.0.0.1", "5432"
fields := strings.Split(DbCfg.Host, ":") fields := strings.Split(DbCfg.Host, ":")

35
models/org.go

@ -18,7 +18,6 @@ var (
ErrTeamAlreadyExist = errors.New("Team already exist") ErrTeamAlreadyExist = errors.New("Team already exist")
ErrTeamNotExist = errors.New("Team does not exist") ErrTeamNotExist = errors.New("Team does not exist")
ErrTeamNameIllegal = errors.New("Team name contains illegal characters") ErrTeamNameIllegal = errors.New("Team name contains illegal characters")
ErrLastOrgOwner = errors.New("The user to remove is the last member in owner team")
) )
// IsOwnedBy returns true if given user is in the owner team. // IsOwnedBy returns true if given user is in the owner team.
@ -339,18 +338,20 @@ func RemoveOrgUser(orgId, uid int64) error {
has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou) has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
if err != nil { if err != nil {
return err return fmt.Errorf("get org-user: %v", err)
} else if !has { } else if !has {
return nil return nil
} }
u, err := GetUserById(uid) u, err := GetUserById(uid)
if err != nil { if err != nil {
return err return fmt.Errorf("GetUserById: %v", err)
} }
org, err := GetUserById(orgId) org, err := GetUserById(orgId)
if err != nil { if err != nil {
return err return fmt.Errorf("get organization: %v", err)
} else if err = org.GetRepositories(); err != nil {
return fmt.Errorf("GetRepositories: %v", err)
} }
// Check if the user to delete is the last member in owner team. // Check if the user to delete is the last member in owner team.
@ -360,49 +361,39 @@ func RemoveOrgUser(orgId, uid int64) error {
return err return err
} }
if t.NumMembers == 1 { if t.NumMembers == 1 {
return ErrLastOrgOwner return ErrLastOrgOwner{UID: uid}
} }
} }
sess := x.NewSession() sess := x.NewSession()
defer sess.Close() defer sessionRelease(sess)
if err := sess.Begin(); err != nil { if err := sess.Begin(); err != nil {
return err return err
} }
if _, err := sess.Id(ou.ID).Delete(ou); err != nil { if _, err := sess.Id(ou.ID).Delete(ou); err != nil {
sess.Rollback()
return err return err
} else if _, err = sess.Exec("UPDATE `user` SET num_members=num_members-1 WHERE id = ?", orgId); err != nil { } else if _, err = sess.Exec("UPDATE `user` SET num_members=num_members-1 WHERE id=?", orgId); err != nil {
sess.Rollback()
return err return err
} }
// Delete all repository accesses. // Delete all repository accesses.
if err = org.GetRepositories(); err != nil { access := &Access{UserID: u.Id}
sess.Rollback()
return err
}
access := &Access{
UserID: u.Id,
}
for _, repo := range org.Repos { for _, repo := range org.Repos {
access.RepoID = repo.Id access.RepoID = repo.Id
if _, err = sess.Delete(access); err != nil { if _, err = sess.Delete(access); err != nil {
sess.Rollback()
return err return err
} else if err = WatchRepo(u.Id, repo.Id, false); err != nil { } else if err = watchRepo(sess, u.Id, repo.Id, false); err != nil {
sess.Rollback()
return err return err
} }
} }
// Delete member in his/her teams. // Delete member in his/her teams.
ts, err := GetUserTeams(org.Id, u.Id) teams, err := getUserTeams(sess, org.Id, u.Id)
if err != nil { if err != nil {
return err return err
} }
for _, t := range ts { for _, t := range teams {
if err = removeTeamMember(sess, org.Id, t.ID, u.Id); err != nil { if err = removeTeamMember(sess, org.Id, t.ID, u.Id); err != nil {
return err return err
} }
@ -902,7 +893,7 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error {
// Check if the user to delete is the last member in owner team. // Check if the user to delete is the last member in owner team.
if t.IsOwnerTeam() && t.NumMembers == 1 { if t.IsOwnerTeam() && t.NumMembers == 1 {
return ErrLastOrgOwner return ErrLastOrgOwner{UID: uid}
} }
t.NumMembers-- t.NumMembers--

9
models/publickey.go

@ -254,15 +254,16 @@ func saveAuthorizedKeyFile(keys ...*PublicKey) error {
} }
defer f.Close() defer f.Close()
finfo, err := f.Stat() fi, err := f.Stat()
if err != nil { if err != nil {
return err return err
} }
// FIXME: following command does not support in Windows. // FIXME: following command does not support in Windows.
if !setting.IsWindows { if !setting.IsWindows {
if finfo.Mode().Perm() > 0600 { // .ssh directory should have mode 700, and authorized_keys file should have mode 600.
log.Error(4, "authorized_keys file has unusual permission flags: %s - setting to -rw-------", finfo.Mode().Perm().String()) if fi.Mode().Perm() > 0600 {
log.Error(4, "authorized_keys file has unusual permission flags: %s - setting to -rw-------", fi.Mode().Perm().String())
if err = f.Chmod(0600); err != nil { if err = f.Chmod(0600); err != nil {
return err return err
} }
@ -433,7 +434,7 @@ func RewriteAllPublicKeys() error {
defer sshOpLocker.Unlock() defer sshOpLocker.Unlock()
tmpPath := filepath.Join(SSHPath, "authorized_keys.tmp") tmpPath := filepath.Join(SSHPath, "authorized_keys.tmp")
f, err := os.Create(tmpPath) f, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil { if err != nil {
return err return err
} }

168
models/repo.go

@ -23,6 +23,7 @@ import (
"github.com/Unknwon/com" "github.com/Unknwon/com"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/bindata"
"github.com/gogits/gogs/modules/git" "github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/process" "github.com/gogits/gogs/modules/process"
@ -35,7 +36,6 @@ const (
var ( var (
ErrRepoAlreadyExist = errors.New("Repository already exist") ErrRepoAlreadyExist = errors.New("Repository already exist")
ErrRepoNotExist = errors.New("Repository does not exist")
ErrRepoFileNotExist = errors.New("Repository file does not exist") ErrRepoFileNotExist = errors.New("Repository file does not exist")
ErrRepoNameIllegal = errors.New("Repository name contains illegal characters") ErrRepoNameIllegal = errors.New("Repository name contains illegal characters")
ErrRepoFileNotLoaded = errors.New("Repository file not loaded") ErrRepoFileNotLoaded = errors.New("Repository file not loaded")
@ -56,7 +56,7 @@ func LoadRepoConfig() {
types := []string{"gitignore", "license"} types := []string{"gitignore", "license"}
typeFiles := make([][]string, 2) typeFiles := make([][]string, 2)
for i, t := range types { for i, t := range types {
files, err := com.StatDir(path.Join("conf", t)) files, err := bindata.AssetDir("conf/" + t)
if err != nil { if err != nil {
log.Fatal(4, "Fail to get %s files: %v", t, err) log.Fatal(4, "Fail to get %s files: %v", t, err)
} }
@ -348,7 +348,7 @@ func MigrateRepository(u *User, name, desc string, private, mirror bool, url str
return repo, err return repo, err
} }
repo.IsMirror = true repo.IsMirror = true
return repo, UpdateRepository(repo) return repo, UpdateRepository(repo, false)
} else { } else {
os.RemoveAll(repoPath) os.RemoveAll(repoPath)
} }
@ -363,18 +363,7 @@ func MigrateRepository(u *User, name, desc string, private, mirror bool, url str
return repo, fmt.Errorf("create update hook: %v", err) return repo, fmt.Errorf("create update hook: %v", err)
} }
return repo, UpdateRepository(repo) return repo, UpdateRepository(repo, false)
}
// extractGitBareZip extracts git-bare.zip to repository path.
func extractGitBareZip(repoPath string) error {
z, err := zip.Open(path.Join(setting.ConfRootPath, "content/git-bare.zip"))
if err != nil {
return err
}
defer z.Close()
return z.ExtractTo(repoPath)
} }
// initRepoCommit temporarily changes with work directory. // initRepoCommit temporarily changes with work directory.
@ -407,12 +396,14 @@ func createUpdateHook(repoPath string) error {
} }
// InitRepository initializes README and .gitignore if needed. // InitRepository initializes README and .gitignore if needed.
func initRepository(e Engine, f string, u *User, repo *Repository, initReadme bool, repoLang, license string) error { func initRepository(e Engine, repoPath string, u *User, repo *Repository, initReadme bool, repoLang, license string) error {
repoPath := RepoPath(u.Name, repo.Name) // Init bare new repository.
os.MkdirAll(repoPath, os.ModePerm)
// Create bare new repository. _, stderr, err := process.ExecDir(-1, repoPath,
if err := extractGitBareZip(repoPath); err != nil { fmt.Sprintf("initRepository(git init --bare): %s", repoPath),
return err "git", "init", "--bare")
if err != nil {
return errors.New("git init --bare: " + stderr)
} }
if err := createUpdateHook(repoPath); err != nil { if err := createUpdateHook(repoPath); err != nil {
@ -435,11 +426,11 @@ func initRepository(e Engine, f string, u *User, repo *Repository, initReadme bo
tmpDir := filepath.Join(os.TempDir(), com.ToStr(time.Now().Nanosecond())) tmpDir := filepath.Join(os.TempDir(), com.ToStr(time.Now().Nanosecond()))
os.MkdirAll(tmpDir, os.ModePerm) os.MkdirAll(tmpDir, os.ModePerm)
_, stderr, err := process.Exec( _, stderr, err = process.Exec(
fmt.Sprintf("initRepository(git clone): %s", repoPath), fmt.Sprintf("initRepository(git clone): %s", repoPath),
"git", "clone", repoPath, tmpDir) "git", "clone", repoPath, tmpDir)
if err != nil { if err != nil {
return errors.New("initRepository(git clone): " + stderr) return errors.New("git clone: " + stderr)
} }
// README // README
@ -452,43 +443,36 @@ func initRepository(e Engine, f string, u *User, repo *Repository, initReadme bo
} }
} }
// FIXME: following two can be merged.
// .gitignore // .gitignore
filePath := "conf/gitignore/" + repoLang // Copy custom file when available.
if com.IsFile(filePath) { customPath := path.Join(setting.CustomPath, "conf/gitignore", repoLang)
targetPath := path.Join(tmpDir, fileName["gitign"]) targetPath := path.Join(tmpDir, fileName["gitign"])
if com.IsFile(filePath) { if com.IsFile(customPath) {
if err = com.Copy(filePath, targetPath); err != nil { if err := com.Copy(customPath, targetPath); err != nil {
return err return fmt.Errorf("copy gitignore: %v", err)
} }
} else { } else if com.IsSliceContainsStr(Gitignores, repoLang) {
// Check custom files. if err = ioutil.WriteFile(targetPath,
filePath = path.Join(setting.CustomPath, "conf/gitignore", repoLang) bindata.MustAsset(path.Join("conf/gitignore", repoLang)), os.ModePerm); err != nil {
if com.IsFile(filePath) { return fmt.Errorf("generate gitignore: %v", err)
if err := com.Copy(filePath, targetPath); err != nil {
return err
}
}
} }
} else { } else {
delete(fileName, "gitign") delete(fileName, "gitign")
} }
// LICENSE // LICENSE
filePath = "conf/license/" + license customPath = path.Join(setting.CustomPath, "conf/license", license)
if com.IsFile(filePath) { targetPath = path.Join(tmpDir, fileName["license"])
targetPath := path.Join(tmpDir, fileName["license"]) if com.IsFile(customPath) {
if com.IsFile(filePath) { if err = com.Copy(customPath, targetPath); err != nil {
if err = com.Copy(filePath, targetPath); err != nil { return fmt.Errorf("copy license: %v", err)
return err }
} } else if com.IsSliceContainsStr(Licenses, license) {
} else { if err = ioutil.WriteFile(targetPath,
// Check custom files. bindata.MustAsset(path.Join("conf/license", license)), os.ModePerm); err != nil {
filePath = path.Join(setting.CustomPath, "conf/license", license) return fmt.Errorf("generate license: %v", err)
if com.IsFile(filePath) {
if err := com.Copy(filePath, targetPath); err != nil {
return err
}
}
} }
} else { } else {
delete(fileName, "license") delete(fileName, "license")
@ -502,7 +486,7 @@ func initRepository(e Engine, f string, u *User, repo *Repository, initReadme bo
} }
repo.IsBare = true repo.IsBare = true
repo.DefaultBranch = "master" repo.DefaultBranch = "master"
return updateRepository(e, repo) return updateRepository(e, repo, false)
} }
// Apply changes and commit. // Apply changes and commit.
@ -734,7 +718,7 @@ func ChangeRepositoryName(userName, oldRepoName, newRepoName string) (err error)
return os.Rename(RepoPath(userName, oldRepoName), RepoPath(userName, newRepoName)) return os.Rename(RepoPath(userName, oldRepoName), RepoPath(userName, newRepoName))
} }
func updateRepository(e Engine, repo *Repository) error { func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err error) {
repo.LowerName = strings.ToLower(repo.Name) repo.LowerName = strings.ToLower(repo.Name)
if len(repo.Description) > 255 { if len(repo.Description) > 255 {
@ -743,12 +727,40 @@ func updateRepository(e Engine, repo *Repository) error {
if len(repo.Website) > 255 { if len(repo.Website) > 255 {
repo.Website = repo.Website[:255] repo.Website = repo.Website[:255]
} }
_, err := e.Id(repo.Id).AllCols().Update(repo)
return err if _, err = e.Id(repo.Id).AllCols().Update(repo); err != nil {
return fmt.Errorf("update: %v", err)
}
if visibilityChanged {
if err = repo.getOwner(e); err != nil {
return fmt.Errorf("getOwner: %v", err)
}
if !repo.Owner.IsOrganization() {
return nil
}
// Organization repository need to recalculate access table when visivility is changed.
if err = repo.recalculateTeamAccesses(e, 0); err != nil {
return fmt.Errorf("recalculateTeamAccesses: %v", err)
}
}
return nil
} }
func UpdateRepository(repo *Repository) error { func UpdateRepository(repo *Repository, visibilityChanged bool) (err error) {
return updateRepository(x, repo) sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
if err = updateRepository(x, repo, visibilityChanged); err != nil {
return fmt.Errorf("updateRepository: %v", err)
}
return sess.Commit()
} }
// DeleteRepository deletes a repository for a user or organization. // DeleteRepository deletes a repository for a user or organization.
@ -758,7 +770,7 @@ func DeleteRepository(uid, repoID int64, userName string) error {
if err != nil { if err != nil {
return err return err
} else if !has { } else if !has {
return ErrRepoNotExist return ErrRepoNotExist{repoID, uid, ""}
} }
// In case is a organization. // In case is a organization.
@ -792,9 +804,9 @@ func DeleteRepository(uid, repoID int64, userName string) error {
return err return err
} else if _, err = sess.Delete(&Access{RepoID: repo.Id}); err != nil { } else if _, err = sess.Delete(&Access{RepoID: repo.Id}); err != nil {
return err return err
} else if _, err = sess.Delete(&Action{RepoId: repo.Id}); err != nil { } else if _, err = sess.Delete(&Action{RepoID: repo.Id}); err != nil {
return err return err
} else if _, err = sess.Delete(&Watch{RepoId: repoID}); err != nil { } else if _, err = sess.Delete(&Watch{RepoID: repoID}); err != nil {
return err return err
} else if _, err = sess.Delete(&Mirror{RepoId: repoID}); err != nil { } else if _, err = sess.Delete(&Mirror{RepoId: repoID}); err != nil {
return err return err
@ -875,18 +887,18 @@ func GetRepositoryByName(uid int64, repoName string) (*Repository, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} else if !has { } else if !has {
return nil, ErrRepoNotExist return nil, ErrRepoNotExist{0, uid, repoName}
} }
return repo, err return repo, err
} }
func getRepositoryById(e Engine, id int64) (*Repository, error) { func getRepositoryById(e Engine, id int64) (*Repository, error) {
repo := &Repository{} repo := new(Repository)
has, err := e.Id(id).Get(repo) has, err := e.Id(id).Get(repo)
if err != nil { if err != nil {
return nil, err return nil, err
} else if !has { } else if !has {
return nil, ErrRepoNotExist return nil, ErrRepoNotExist{id, 0, ""}
} }
return repo, nil return repo, nil
} }
@ -1163,9 +1175,9 @@ func (repo *Repository) DeleteCollaborator(u *User) (err error) {
// Watch is connection request for receiving repository notification. // Watch is connection request for receiving repository notification.
type Watch struct { type Watch struct {
Id int64 ID int64 `xorm:"pk autoincr"`
UserId int64 `xorm:"UNIQUE(watch)"` UserID int64 `xorm:"UNIQUE(watch)"`
RepoId int64 `xorm:"UNIQUE(watch)"` RepoID int64 `xorm:"UNIQUE(watch)"`
} }
// IsWatching checks if user has watched given repository. // IsWatching checks if user has watched given repository.
@ -1179,7 +1191,7 @@ func watchRepo(e Engine, uid, repoId int64, watch bool) (err error) {
if IsWatching(uid, repoId) { if IsWatching(uid, repoId) {
return nil return nil
} }
if _, err = e.Insert(&Watch{RepoId: repoId, UserId: uid}); err != nil { if _, err = e.Insert(&Watch{RepoID: repoId, UserID: uid}); err != nil {
return err return err
} }
_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?", repoId) _, err = e.Exec("UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?", repoId)
@ -1190,7 +1202,7 @@ func watchRepo(e Engine, uid, repoId int64, watch bool) (err error) {
if _, err = e.Delete(&Watch{0, uid, repoId}); err != nil { if _, err = e.Delete(&Watch{0, uid, repoId}); err != nil {
return err return err
} }
_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?", repoId) _, err = e.Exec("UPDATE `repository` SET num_watches=num_watches-1 WHERE id=?", repoId)
} }
return err return err
} }
@ -1202,7 +1214,7 @@ func WatchRepo(uid, repoId int64, watch bool) (err error) {
func getWatchers(e Engine, rid int64) ([]*Watch, error) { func getWatchers(e Engine, rid int64) ([]*Watch, error) {
watches := make([]*Watch, 0, 10) watches := make([]*Watch, 0, 10)
err := e.Find(&watches, &Watch{RepoId: rid}) err := e.Find(&watches, &Watch{RepoID: rid})
return watches, err return watches, err
} }
@ -1213,24 +1225,24 @@ func GetWatchers(rid int64) ([]*Watch, error) {
func notifyWatchers(e Engine, act *Action) error { func notifyWatchers(e Engine, act *Action) error {
// Add feeds for user self and all watchers. // Add feeds for user self and all watchers.
watches, err := getWatchers(e, act.RepoId) watches, err := getWatchers(e, act.RepoID)
if err != nil { if err != nil {
return fmt.Errorf("get watchers: %v", err) return fmt.Errorf("get watchers: %v", err)
} }
// Add feed for actioner. // Add feed for actioner.
act.UserId = act.ActUserId act.UserID = act.ActUserID
if _, err = e.InsertOne(act); err != nil { if _, err = e.InsertOne(act); err != nil {
return fmt.Errorf("insert new actioner: %v", err) return fmt.Errorf("insert new actioner: %v", err)
} }
for i := range watches { for i := range watches {
if act.ActUserId == watches[i].UserId { if act.ActUserID == watches[i].UserID {
continue continue
} }
act.Id = 0 act.ID = 0
act.UserId = watches[i].UserId act.UserID = watches[i].UserID
if _, err = e.InsertOne(act); err != nil { if _, err = e.InsertOne(act); err != nil {
return fmt.Errorf("insert new action: %v", err) return fmt.Errorf("insert new action: %v", err)
} }
@ -1377,5 +1389,9 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
return nil, fmt.Errorf("git update-server-info: %v", err) return nil, fmt.Errorf("git update-server-info: %v", err)
} }
if err = createUpdateHook(repoPath); err != nil {
return nil, fmt.Errorf("createUpdateHook: %v", err)
}
return repo, sess.Commit() return repo, sess.Commit()
} }

89
models/user.go

@ -36,8 +36,6 @@ const (
) )
var ( var (
ErrUserOwnRepos = errors.New("User still have ownership of repositories")
ErrUserHasOrgs = errors.New("User still have membership of organization")
ErrUserAlreadyExist = errors.New("User already exist") ErrUserAlreadyExist = errors.New("User already exist")
ErrUserNotExist = errors.New("User does not exist") ErrUserNotExist = errors.New("User does not exist")
ErrUserNotKeyOwner = errors.New("User does not the owner of public key") ErrUserNotKeyOwner = errors.New("User does not the owner of public key")
@ -124,7 +122,7 @@ func (u *User) AvatarLink() string {
switch { switch {
case u.UseCustomAvatar: case u.UseCustomAvatar:
return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id) return setting.AppSubUrl + "/avatars/" + com.ToStr(u.Id)
case setting.DisableGravatar: case setting.DisableGravatar, setting.OfflineMode:
return setting.AppSubUrl + "/img/avatar_default.jpg" return setting.AppSubUrl + "/img/avatar_default.jpg"
case setting.Service.EnableCacheAvatar: case setting.Service.EnableCacheAvatar:
return setting.AppSubUrl + "/avatar/" + u.Avatar return setting.AppSubUrl + "/avatar/" + u.Avatar
@ -432,55 +430,75 @@ func UpdateUser(u *User) error {
return err return err
} }
// DeleteBeans deletes all given beans, beans should contain delete conditions.
func DeleteBeans(e Engine, beans ...interface{}) (err error) {
for i := range beans {
if _, err = e.Delete(beans[i]); err != nil {
return err
}
}
return nil
}
// FIXME: need some kind of mechanism to record failure. HINT: system notice // FIXME: need some kind of mechanism to record failure. HINT: system notice
// DeleteUser completely and permanently deletes everything of user. // DeleteUser completely and permanently deletes everything of user.
func DeleteUser(u *User) error { func DeleteUser(u *User) error {
// Check ownership of repository. // Check ownership of repository.
count, err := GetRepositoryCount(u) count, err := GetRepositoryCount(u)
if err != nil { if err != nil {
return errors.New("GetRepositoryCount: " + err.Error()) return fmt.Errorf("GetRepositoryCount: %v", err)
} else if count > 0 { } else if count > 0 {
return ErrUserOwnRepos return ErrUserOwnRepos{UID: u.Id}
} }
// Check membership of organization. // Check membership of organization.
count, err = u.GetOrganizationCount() count, err = u.GetOrganizationCount()
if err != nil { if err != nil {
return errors.New("GetOrganizationCount: " + err.Error()) return fmt.Errorf("GetOrganizationCount: %v", err)
} else if count > 0 { } else if count > 0 {
return ErrUserHasOrgs return ErrUserHasOrgs{UID: u.Id}
} }
// FIXME: check issues, other repos' commits // Get watches before session.
// FIXME: roll backable in some point. watches := make([]*Watch, 0, 10)
if err = x.Where("user_id=?", u.Id).Find(&watches); err != nil {
// Delete all followers. return fmt.Errorf("get all watches: %v", err)
if _, err = x.Delete(&Follow{FollowId: u.Id}); err != nil {
return err
} }
// Delete oauth2. repoIDs := make([]int64, 0, len(watches))
if _, err = x.Delete(&Oauth2{Uid: u.Id}); err != nil { for i := range watches {
return err repoIDs = append(repoIDs, watches[i].RepoID)
} }
// Delete all feeds.
if _, err = x.Delete(&Action{UserId: u.Id}); err != nil { // FIXME: check issues, other repos' commits
return err
} sess := x.NewSession()
// Delete all watches. defer sessionRelease(sess)
if _, err = x.Delete(&Watch{UserId: u.Id}); err != nil { if err = sess.Begin(); err != nil {
return err return err
} }
// Delete all accesses.
if _, err = x.Delete(&Access{UserID: u.Id}); err != nil { if err = DeleteBeans(sess,
&Follow{FollowID: u.Id},
&Oauth2{Uid: u.Id},
&Action{UserID: u.Id},
&Access{UserID: u.Id},
&Collaboration{UserID: u.Id},
&EmailAddress{Uid: u.Id},
&Watch{UserID: u.Id},
); err != nil {
return err return err
} }
// Delete all alternative email addresses
if _, err = x.Delete(&EmailAddress{Uid: u.Id}); err != nil { // Decrease all watch numbers.
return err for i := range repoIDs {
if _, err = sess.Exec("UPDATE `repository` SET num_watches=num_watches-1 WHERE id=?", repoIDs[i]); err != nil {
return err
}
} }
// Delete all SSH keys. // Delete all SSH keys.
keys := make([]*PublicKey, 0, 10) keys := make([]*PublicKey, 0, 10)
if err = x.Find(&keys, &PublicKey{OwnerId: u.Id}); err != nil { if err = sess.Find(&keys, &PublicKey{OwnerId: u.Id}); err != nil {
return err return err
} }
for _, key := range keys { for _, key := range keys {
@ -489,13 +507,16 @@ func DeleteUser(u *User) error {
} }
} }
if _, err = sess.Delete(u); err != nil {
return err
}
// Delete user directory. // Delete user directory.
if err = os.RemoveAll(UserPath(u.Name)); err != nil { if err = os.RemoveAll(UserPath(u.Name)); err != nil {
return err return err
} }
_, err = x.Delete(u) return sess.Commit()
return err
} }
// DeleteInactivateUsers deletes all inactivate users and email addresses. // DeleteInactivateUsers deletes all inactivate users and email addresses.
@ -777,8 +798,8 @@ func SearchUserByName(opt SearchOption) (us []*User, err error) {
// Follow is connection request for receiving user notification. // Follow is connection request for receiving user notification.
type Follow struct { type Follow struct {
Id int64 Id int64
UserId int64 `xorm:"unique(follow)"` UserID int64 `xorm:"unique(follow)"`
FollowId int64 `xorm:"unique(follow)"` FollowID int64 `xorm:"unique(follow)"`
} }
// FollowUser marks someone be another's follower. // FollowUser marks someone be another's follower.
@ -787,7 +808,7 @@ func FollowUser(userId int64, followId int64) (err error) {
defer sess.Close() defer sess.Close()
sess.Begin() sess.Begin()
if _, err = sess.Insert(&Follow{UserId: userId, FollowId: followId}); err != nil { if _, err = sess.Insert(&Follow{UserID: userId, FollowID: followId}); err != nil {
sess.Rollback() sess.Rollback()
return err return err
} }
@ -812,7 +833,7 @@ func UnFollowUser(userId int64, unFollowId int64) (err error) {
defer session.Close() defer session.Close()
session.Begin() session.Begin()
if _, err = session.Delete(&Follow{UserId: userId, FollowId: unFollowId}); err != nil { if _, err = session.Delete(&Follow{UserID: userId, FollowID: unFollowId}); err != nil {
session.Rollback() session.Rollback()
return err return err
} }

2
models/webhook.go

@ -205,7 +205,7 @@ func IsValidHookTaskType(name string) bool {
type HookEventType string type HookEventType string
const ( const (
PUSH HookEventType = "push" HOOK_EVENT_PUSH HookEventType = "push"
) )
// FIXME: just use go-gogs-client structs maybe? // FIXME: just use go-gogs-client structs maybe?

18
modules/auth/admin.go

@ -11,15 +11,15 @@ import (
) )
type AdminEditUserForm struct { type AdminEditUserForm struct {
Email string `form:"email" binding:"Required;Email;MaxSize(50)"` Email string `binding:"Required;Email;MaxSize(50)"`
Passwd string `form:"password"` Password string `binding:"OmitEmpty;MinSize(6);MaxSize(255)"`
Website string `form:"website" binding:"MaxSize(50)"` Website string `binding:"MaxSize(50)"`
Location string `form:"location" binding:"MaxSize(50)"` Location string `binding:"MaxSize(50)"`
Avatar string `form:"avatar" binding:"Required;Email;MaxSize(50)"` Avatar string `binding:"Required;Email;MaxSize(50)"`
Active bool `form:"active"` Active bool
Admin bool `form:"admin"` Admin bool
AllowGitHook bool `form:"allow_git_hook"` AllowGitHook bool
LoginType int `form:"login_type"` LoginType int
} }
func (f *AdminEditUserForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { func (f *AdminEditUserForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {

14
modules/auth/repo_form.go

@ -32,13 +32,13 @@ func (f *CreateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) bin
type MigrateRepoForm struct { type MigrateRepoForm struct {
CloneAddr string `binding:"Required"` CloneAddr string `binding:"Required"`
AuthUserName string `form:"auth_username"` AuthUsername string
AuthPasswd string `form:"auth_password"` AuthPassword string
Uid int64 `form:"uid" binding:"Required"` Uid int64 `binding:"Required"`
RepoName string `form:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"` RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
Mirror bool `form:"mirror"` Mirror bool
Private bool `form:"private"` Private bool
Description string `form:"desc" binding:"MaxSize(255)"` Description string `binding:"MaxSize(255)"`
} }
func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {

2
modules/base/tool.go

@ -171,7 +171,7 @@ func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string
// AvatarLink returns avatar link by given e-mail. // AvatarLink returns avatar link by given e-mail.
func AvatarLink(email string) string { func AvatarLink(email string) string {
if setting.DisableGravatar { if setting.DisableGravatar || setting.OfflineMode {
return setting.AppSubUrl + "/img/avatar_default.jpg" return setting.AppSubUrl + "/img/avatar_default.jpg"
} }

1041
modules/bindata/bindata.go

File diff suppressed because one or more lines are too long

4
modules/git/commit.go

@ -88,11 +88,11 @@ func (c *Commit) GetCommitOfRelPath(relPath string) (*Commit, error) {
} }
func (c *Commit) GetSubModule(entryname string) (*SubModule, error) { func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
moduels, err := c.GetSubModules() modules, err := c.GetSubModules()
if err != nil { if err != nil {
return nil, err return nil, err
} }
return moduels[entryname], nil return modules[entryname], nil
} }
func (c *Commit) GetSubModules() (map[string]*SubModule, error) { func (c *Commit) GetSubModules() (map[string]*SubModule, error) {

4
modules/git/submodule.go

@ -31,6 +31,10 @@ func NewSubModuleFile(c *Commit, refUrl, refId string) *SubModuleFile {
// RefUrl guesses and returns reference URL. // RefUrl guesses and returns reference URL.
func (sf *SubModuleFile) RefUrl() string { func (sf *SubModuleFile) RefUrl() string {
if sf.refUrl == "" {
return ""
}
url := strings.TrimSuffix(sf.refUrl, ".git") url := strings.TrimSuffix(sf.refUrl, ".git")
// git://xxx/user/repo // git://xxx/user/repo

2
modules/mailer/mail.go

@ -163,7 +163,7 @@ func SendIssueNotifyMail(u, owner *models.User, repo *models.Repository, issue *
tos := make([]string, 0, len(ws)) tos := make([]string, 0, len(ws))
for i := range ws { for i := range ws {
uid := ws[i].UserId uid := ws[i].UserID
if u.Id == uid { if u.Id == uid {
continue continue
} }

2
modules/middleware/auth.go

@ -30,7 +30,7 @@ func Toggle(options *ToggleOptions) macaron.Handler {
// Checking non-logged users landing page. // Checking non-logged users landing page.
if !ctx.IsSigned && ctx.Req.RequestURI == "/" && setting.LandingPageUrl != setting.LANDING_PAGE_HOME { if !ctx.IsSigned && ctx.Req.RequestURI == "/" && setting.LandingPageUrl != setting.LANDING_PAGE_HOME {
ctx.Redirect(string(setting.LandingPageUrl)) ctx.Redirect(setting.AppSubUrl + string(setting.LandingPageUrl))
return return
} }

4
modules/middleware/repo.go

@ -47,7 +47,7 @@ func ApiRepoAssignment() macaron.Handler {
// Get repository. // Get repository.
repo, err := models.GetRepositoryByName(u.Id, repoName) repo, err := models.GetRepositoryByName(u.Id, repoName)
if err != nil { if err != nil {
if err == models.ErrRepoNotExist { if models.IsErrRepoNotExist(err) {
ctx.Error(404) ctx.Error(404)
} else { } else {
ctx.JSON(500, &base.ApiJsonErr{"GetRepositoryByName: " + err.Error(), base.DOC_URL}) ctx.JSON(500, &base.ApiJsonErr{"GetRepositoryByName: " + err.Error(), base.DOC_URL})
@ -223,7 +223,7 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
// Get repository. // Get repository.
repo, err := models.GetRepositoryByName(u.Id, repoName) repo, err := models.GetRepositoryByName(u.Id, repoName)
if err != nil { if err != nil {
if err == models.ErrRepoNotExist { if models.IsErrRepoNotExist(err) {
ctx.Handle(404, "GetRepositoryByName", err) ctx.Handle(404, "GetRepositoryByName", err)
} else { } else {
ctx.Handle(500, "GetRepositoryByName", err) ctx.Handle(500, "GetRepositoryByName", err)

24
modules/setting/setting.go

@ -20,6 +20,7 @@ import (
"github.com/macaron-contrib/session" "github.com/macaron-contrib/session"
"gopkg.in/ini.v1" "gopkg.in/ini.v1"
"github.com/gogits/gogs/modules/bindata"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
// "github.com/gogits/gogs/modules/ssh" // "github.com/gogits/gogs/modules/ssh"
) )
@ -131,7 +132,6 @@ var (
// Global setting objects. // Global setting objects.
Cfg *ini.File Cfg *ini.File
ConfRootPath string
CustomPath string // Custom directory path. CustomPath string // Custom directory path.
CustomConf string CustomConf string
ProdMode bool ProdMode bool
@ -163,6 +163,12 @@ func WorkDir() (string, error) {
return path.Dir(strings.Replace(execPath, "\\", "/", -1)), err return path.Dir(strings.Replace(execPath, "\\", "/", -1)), err
} }
func forcePathSeparator(path string) {
if strings.Contains(path, "\\") {
log.Fatal(4, "Do not use '\\' or '\\\\' in paths, instead, please use '/' in all places")
}
}
// NewConfigContext initializes configuration context. // NewConfigContext initializes configuration context.
// NOTE: do not print any log except error. // NOTE: do not print any log except error.
func NewConfigContext() { func NewConfigContext() {
@ -170,9 +176,8 @@ func NewConfigContext() {
if err != nil { if err != nil {
log.Fatal(4, "Fail to get work directory: %v", err) log.Fatal(4, "Fail to get work directory: %v", err)
} }
ConfRootPath = path.Join(workDir, "conf")
Cfg, err = ini.Load(path.Join(workDir, "conf/app.ini")) Cfg, err = ini.Load(bindata.MustAsset("conf/app.ini"))
if err != nil { if err != nil {
log.Fatal(4, "Fail to parse 'conf/app.ini': %v", err) log.Fatal(4, "Fail to parse 'conf/app.ini': %v", err)
} }
@ -196,6 +201,7 @@ func NewConfigContext() {
Cfg.NameMapper = ini.AllCapsUnderscore Cfg.NameMapper = ini.AllCapsUnderscore
LogRootPath = Cfg.Section("log").Key("ROOT_PATH").MustString(path.Join(workDir, "log")) LogRootPath = Cfg.Section("log").Key("ROOT_PATH").MustString(path.Join(workDir, "log"))
forcePathSeparator(LogRootPath)
sec := Cfg.Section("server") sec := Cfg.Section("server")
AppName = Cfg.Section("").Key("APP_NAME").MustString("Gogs: Go Git Service") AppName = Cfg.Section("").Key("APP_NAME").MustString("Gogs: Go Git Service")
@ -287,18 +293,22 @@ func NewConfigContext() {
if err != nil { if err != nil {
log.Fatal(4, "Fail to get home directory: %v", err) log.Fatal(4, "Fail to get home directory: %v", err)
} }
homeDir = strings.Replace(homeDir, "\\", "/", -1)
sec = Cfg.Section("repository") sec = Cfg.Section("repository")
RepoRootPath = sec.Key("ROOT").MustString(filepath.Join(homeDir, "gogs-repositories")) RepoRootPath = sec.Key("ROOT").MustString(path.Join(homeDir, "gogs-repositories"))
forcePathSeparator(RepoRootPath)
if !filepath.IsAbs(RepoRootPath) { if !filepath.IsAbs(RepoRootPath) {
RepoRootPath = filepath.Join(workDir, RepoRootPath) RepoRootPath = path.Join(workDir, RepoRootPath)
} else { } else {
RepoRootPath = filepath.Clean(RepoRootPath) RepoRootPath = path.Clean(RepoRootPath)
} }
ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash") ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
sec = Cfg.Section("picture") sec = Cfg.Section("picture")
PictureService = sec.Key("SERVICE").In("server", []string{"server"}) PictureService = sec.Key("SERVICE").In("server", []string{"server"})
AvatarUploadPath = sec.Key("AVATAR_UPLOAD_PATH").MustString("data/avatars") AvatarUploadPath = sec.Key("AVATAR_UPLOAD_PATH").MustString("data/avatars")
forcePathSeparator(AvatarUploadPath)
if !filepath.IsAbs(AvatarUploadPath) { if !filepath.IsAbs(AvatarUploadPath) {
AvatarUploadPath = path.Join(workDir, AvatarUploadPath) AvatarUploadPath = path.Join(workDir, AvatarUploadPath)
} }
@ -341,7 +351,7 @@ func newService() {
Service.RequireSignInView = Cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").MustBool() Service.RequireSignInView = Cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").MustBool()
Service.EnableCacheAvatar = Cfg.Section("service").Key("ENABLE_CACHE_AVATAR").MustBool() Service.EnableCacheAvatar = Cfg.Section("service").Key("ENABLE_CACHE_AVATAR").MustBool()
Service.EnableReverseProxyAuth = Cfg.Section("service").Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool() Service.EnableReverseProxyAuth = Cfg.Section("service").Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool()
Service.EnableReverseProxyAutoRegister = Cfg.Section("service").Key("ENABLE_REVERSE_PROXY_AUTO_REGISTERATION").MustBool() Service.EnableReverseProxyAutoRegister = Cfg.Section("service").Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()
} }
var logLevels = map[string]string{ var logLevels = map[string]string{

32
public/ng/css/gogs.css

@ -732,7 +732,8 @@ ol.linenums {
#dashboard-header > .menu-line > li.right > a { #dashboard-header > .menu-line > li.right > a {
font-size: 1.2em; font-size: 1.2em;
color: #444444; color: #444444;
padding: .4em .8em; margin: -12px 0px;
padding: 22px 0.8em;
} }
#dashboard-header > .menu-line > li.right > a:hover { #dashboard-header > .menu-line > li.right > a:hover {
background-color: transparent; background-color: transparent;
@ -2413,6 +2414,35 @@ textarea#issue-add-content {
#milestone-list .action-bar a { #milestone-list .action-bar a {
margin-left: 12px; margin-left: 12px;
} }
.issues.list-group {
margin: 10px 0 20px 0;
}
.issues.list-group > .list-group-item {
background-color: #FFF;
border: 1px solid #e5e5e5;
display: block;
padding: 10px 15px;
margin-bottom: -1px;
}
.issues.list-group > .list-group-item:hover {
background-color: rgba(19, 95, 215, 0.03);
}
.issues.list-group > .list-group-item > .title {
margin-bottom: 16px;
font-weight: bold;
font-size: 1.2em;
}
.issues.list-group > .list-group-item > .title > a {
color: #444;
}
.issues.list-group > .list-group-item > .info span {
margin-right: 12px;
color: #888;
line-height: 20px;
}
.issues.list-group > .list-group-item > .info span > a {
color: #444;
}
.org-header-alert .alert { .org-header-alert .alert {
margin-top: 10px; margin-top: 10px;
} }

37
public/ng/css/ui.css

@ -188,7 +188,8 @@ input:focus,
background-color: #f2fffc; background-color: #f2fffc;
outline: none; outline: none;
} }
button { button,
.btn {
overflow: visible; overflow: visible;
padding: .6em 1.2em; padding: .6em 1.2em;
} }
@ -431,6 +432,19 @@ dt {
background-color: #fafafa; background-color: #fafafa;
color: #444444; color: #444444;
} }
.btn-white {
background-color: #ffffff;
color: #444444;
border: 1px solid #c6c6c6;
}
.btn-white:hover {
background-color: #e8e8e8;
color: #444444;
}
.btn-white.active {
background-color: #e8e8e8;
color: #444444;
}
.btn-active { .btn-active {
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1) inset, 0 0 4px rgba(0, 0, 0, 0.15) inset; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1) inset, 0 0 4px rgba(0, 0, 0, 0.15) inset;
} }
@ -475,6 +489,22 @@ dt {
background-image: none !important; background-image: none !important;
color: #ffffff; color: #ffffff;
} }
.btn-group {
display: inline-block;
}
.btn-group > .btn {
position: relative;
float: left;
margin-right: -1px;
}
.btn-group > .btn:first-child {
border-bottom-left-radius: .25em;
border-top-left-radius: .25em;
}
.btn-group > .btn:last-child {
border-bottom-right-radius: .25em;
border-top-right-radius: .25em;
}
.ipt:focus { .ipt:focus {
border-color: #428bca; border-color: #428bca;
} }
@ -550,6 +580,10 @@ ul.menu > li > a:hover {
background-color: #eaeaea; background-color: #eaeaea;
color: #444444; color: #444444;
} }
ul.menu > li > a.active {
background-color: #4183c4;
color: #FFF;
}
ul.menu > li.current > a, ul.menu > li.current > a,
ul.menu > li.hover > a { ul.menu > li.hover > a {
color: #444444; color: #444444;
@ -597,6 +631,7 @@ ul.menu-vertical > li.head,
ul.menu-down > li.head { ul.menu-down > li.head {
display: block; display: block;
padding: .4em 1.2em; padding: .4em 1.2em;
margin-bottom: 4px;
} }
ul.menu-vertical > li.down, ul.menu-vertical > li.down,
ul.menu-down > li.down { ul.menu-down > li.down {

3
public/ng/less/gogs/dashboard.less

@ -27,7 +27,8 @@
> a { > a {
font-size: 1.2em; font-size: 1.2em;
color: @dashboardHeaderLinkColor; color: @dashboardHeaderLinkColor;
padding: .4em .8em; margin: -12px 0px;
padding: 22px 0.8em;
&:hover { &:hover {
background-color: transparent; background-color: transparent;
color: @dashboardHeaderLinkHoverColor; color: @dashboardHeaderLinkHoverColor;

28
public/ng/less/gogs/issue.less

@ -511,4 +511,30 @@ textarea#issue-add-content {
margin-left: 12px; margin-left: 12px;
} }
} }
} }
.issues.list-group {
margin: 10px 0 20px 0;
> .list-group-item {
background-color: #FFF;
border: 1px solid #e5e5e5;
display: block;
padding: 10px 15px;
margin-bottom: -1px;
&:hover {
background-color: rgba(19, 95, 215, 0.03);
}
> .title {
margin-bottom: 16px;
font-weight: bold;
font-size: 1.2em;
> a { color: #444; }
}
> .info span {
margin-right: 12px;
color: #888;
line-height: 20px;
> a { color: #444; }
}
}
}

31
public/ng/less/ui/form.less

@ -70,6 +70,19 @@
} }
} }
.btn-white {
background-color: @btnWhiteColor;
color: @baseFontColor;
border: 1px solid @btnWhiteBorderColor;
&:hover {
background-color: @btnWhiteHoverColor;
color: @baseFontColor;
}
&.active {
background-color: @btnWhiteHoverColor;
color: @baseFontColor;
}
}
// status buttons // status buttons
.btn-active { .btn-active {
@ -118,6 +131,22 @@
} }
} }
.btn-group {
display: inline-block;
> .btn {
position: relative;
float: left;
margin-right: -1px;
&:first-child{
border-bottom-left-radius: .25em;
border-top-left-radius: .25em;
}
&:last-child{
border-bottom-right-radius: .25em;
border-top-right-radius: .25em;
}
}
}
// input form elements // input form elements
.ipt { .ipt {
&:focus { &:focus {
@ -198,4 +227,4 @@ label {
color: @labelRedColor; color: @labelRedColor;
} }
} }
} }

7
public/ng/less/ui/menu.less

@ -11,6 +11,10 @@ ul.menu {
background-color: @lineMenuHoverBgColor; background-color: @lineMenuHoverBgColor;
color: @lineMenuHoverFontColor; color: @lineMenuHoverFontColor;
} }
&.active {
background-color: #4183c4;
color: #FFF;
}
} }
&.current > a, &.current > a,
&.hover > a { &.hover > a {
@ -67,6 +71,7 @@ ul.menu-down {
> li.head { > li.head {
display: block; display: block;
padding: .4em 1.2em; padding: .4em 1.2em;
margin-bottom: 4px;
} }
> li.down { > li.down {
position: relative; position: relative;
@ -163,4 +168,4 @@ ul.menu-radius {
content: "\25B4"; content: "\25B4";
margin-left: .4em; margin-left: .4em;
} }
} }

4
public/ng/less/ui/reset.less

@ -238,7 +238,7 @@ input,
} }
} }
button { button,.btn {
overflow: visible; overflow: visible;
padding: .6em 1.2em; padding: .6em 1.2em;
} }
@ -365,4 +365,4 @@ pre {
dt { dt {
font-weight: bold; font-weight: bold;
} }

4
public/ng/less/ui/var.less

@ -45,6 +45,10 @@
@btnGrayHoverColor: #FAFAFA; @btnGrayHoverColor: #FAFAFA;
@btnGrayBorderColor: #D0D0D0; @btnGrayBorderColor: #D0D0D0;
@btnWhiteColor: #FFF;
@btnWhiteHoverColor: #e8e8e8;
@btnWhiteBorderColor: #c6c6c6;
@lineMenuHoverBgColor: #EAEAEA; @lineMenuHoverBgColor: #EAEAEA;
@lineMenuHoverFontColor: #444; @lineMenuHoverFontColor: #444;

13
routers/admin/users.go

@ -168,6 +168,7 @@ func EditUserPost(ctx *middleware.Context, form auth.AdminEditUserForm) {
ctx.Handle(500, "GetUserById", err) ctx.Handle(500, "GetUserById", err)
return return
} }
ctx.Data["User"] = u
if ctx.HasError() { if ctx.HasError() {
ctx.HTML(200, USER_EDIT) ctx.HTML(200, USER_EDIT)
@ -175,8 +176,8 @@ func EditUserPost(ctx *middleware.Context, form auth.AdminEditUserForm) {
} }
// FIXME: need password length check // FIXME: need password length check
if len(form.Passwd) > 0 { if len(form.Password) > 0 {
u.Passwd = form.Passwd u.Passwd = form.Password
u.Salt = models.GetUserSalt() u.Salt = models.GetUserSalt()
u.EncodePasswd() u.EncodePasswd()
} }
@ -193,8 +194,6 @@ func EditUserPost(ctx *middleware.Context, form auth.AdminEditUserForm) {
u.IsAdmin = form.Admin u.IsAdmin = form.Admin
u.AllowGitHook = form.AllowGitHook u.AllowGitHook = form.AllowGitHook
ctx.Data["User"] = u
if err := models.UpdateUser(u); err != nil { if err := models.UpdateUser(u); err != nil {
if err == models.ErrEmailAlreadyUsed { if err == models.ErrEmailAlreadyUsed {
ctx.Data["Err_Email"] = true ctx.Data["Err_Email"] = true
@ -223,11 +222,11 @@ func DeleteUser(ctx *middleware.Context) {
} }
if err = models.DeleteUser(u); err != nil { if err = models.DeleteUser(u); err != nil {
switch err { switch {
case models.ErrUserOwnRepos: case models.IsErrUserOwnRepos(err):
ctx.Flash.Error(ctx.Tr("admin.users.still_own_repo")) ctx.Flash.Error(ctx.Tr("admin.users.still_own_repo"))
ctx.Redirect(setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid")) ctx.Redirect(setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid"))
case models.ErrUserHasOrgs: case models.IsErrUserHasOrgs(err):
ctx.Flash.Error(ctx.Tr("admin.users.still_has_org")) ctx.Flash.Error(ctx.Tr("admin.users.still_has_org"))
ctx.Redirect(setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid")) ctx.Redirect(setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid"))
default: default:

6
routers/api/v1/repo.go

@ -196,7 +196,7 @@ func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) {
} }
} }
// Remote address can be HTTPS URL or local path. // Remote address can be HTTP/HTTPS URL or local path.
remoteAddr := form.CloneAddr remoteAddr := form.CloneAddr
if strings.HasPrefix(form.CloneAddr, "http") { if strings.HasPrefix(form.CloneAddr, "http") {
u, err := url.Parse(form.CloneAddr) u, err := url.Parse(form.CloneAddr)
@ -204,8 +204,8 @@ func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) {
ctx.HandleAPI(422, err) ctx.HandleAPI(422, err)
return return
} }
if len(form.AuthUserName) > 0 || len(form.AuthPasswd) > 0 { if len(form.AuthUsername) > 0 || len(form.AuthPassword) > 0 {
u.User = url.UserPassword(form.AuthUserName, form.AuthPasswd) u.User = url.UserPassword(form.AuthUsername, form.AuthPassword)
} }
remoteAddr = u.String() remoteAddr = u.String()
} else if !com.IsDir(remoteAddr) { } else if !com.IsDir(remoteAddr) {

4
routers/org/members.go

@ -61,14 +61,14 @@ func MembersAction(ctx *middleware.Context) {
return return
} }
err = org.RemoveMember(uid) err = org.RemoveMember(uid)
if err == models.ErrLastOrgOwner { if models.IsErrLastOrgOwner(err) {
ctx.Flash.Error(ctx.Tr("form.last_org_owner")) ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
ctx.Redirect(ctx.Org.OrgLink + "/members") ctx.Redirect(ctx.Org.OrgLink + "/members")
return return
} }
case "leave": case "leave":
err = org.RemoveMember(ctx.User.Id) err = org.RemoveMember(ctx.User.Id)
if err == models.ErrLastOrgOwner { if models.IsErrLastOrgOwner(err) {
ctx.Flash.Error(ctx.Tr("form.last_org_owner")) ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
ctx.Redirect(ctx.Org.OrgLink + "/members") ctx.Redirect(ctx.Org.OrgLink + "/members")
return return

7
routers/org/setting.go

@ -87,13 +87,12 @@ func SettingsDelete(ctx *middleware.Context) {
org := ctx.Org.Organization org := ctx.Org.Organization
if ctx.Req.Method == "POST" { if ctx.Req.Method == "POST" {
// TODO: validate password. // FIXME: validate password.
if err := models.DeleteOrganization(org); err != nil { if err := models.DeleteOrganization(org); err != nil {
switch err { if models.IsErrUserOwnRepos(err) {
case models.ErrUserOwnRepos:
ctx.Flash.Error(ctx.Tr("form.org_still_own_repo")) ctx.Flash.Error(ctx.Tr("form.org_still_own_repo"))
ctx.Redirect(setting.AppSubUrl + "/org/" + org.LowerName + "/settings/delete") ctx.Redirect(setting.AppSubUrl + "/org/" + org.LowerName + "/settings/delete")
default: } else {
ctx.Handle(500, "DeleteOrganization", err) ctx.Handle(500, "DeleteOrganization", err)
} }
} else { } else {

4
routers/org/teams.go

@ -91,7 +91,7 @@ func TeamsAction(ctx *middleware.Context) {
} }
if err != nil { if err != nil {
if err == models.ErrLastOrgOwner { if models.IsErrLastOrgOwner(err) {
ctx.Flash.Error(ctx.Tr("form.last_org_owner")) ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
} else { } else {
log.Error(3, "Action(%s): %v", ctx.Params(":action"), err) log.Error(3, "Action(%s): %v", ctx.Params(":action"), err)
@ -124,7 +124,7 @@ func TeamsRepoAction(ctx *middleware.Context) {
var repo *models.Repository var repo *models.Repository
repo, err = models.GetRepositoryByName(ctx.Org.Organization.Id, repoName) repo, err = models.GetRepositoryByName(ctx.Org.Organization.Id, repoName)
if err != nil { if err != nil {
if err == models.ErrRepoNotExist { if models.IsErrRepoNotExist(err) {
ctx.Flash.Error(ctx.Tr("org.teams.add_nonexistent_repo")) ctx.Flash.Error(ctx.Tr("org.teams.add_nonexistent_repo"))
ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories") ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories")
return return

47
routers/repo/http.go

@ -65,7 +65,7 @@ func Http(ctx *middleware.Context) {
repo, err := models.GetRepositoryByName(repoUser.Id, reponame) repo, err := models.GetRepositoryByName(repoUser.Id, reponame)
if err != nil { if err != nil {
if err == models.ErrRepoNotExist { if models.IsErrRepoNotExist(err) {
ctx.Handle(404, "GetRepositoryByName", nil) ctx.Handle(404, "GetRepositoryByName", nil)
} else { } else {
ctx.Handle(500, "GetRepositoryByName", err) ctx.Handle(500, "GetRepositoryByName", err)
@ -105,7 +105,7 @@ func Http(ctx *middleware.Context) {
return return
} }
authUser, err := models.UserSignIn(authUsername, authPasswd) authUser, err = models.UserSignIn(authUsername, authPasswd)
if err != nil { if err != nil {
if err != models.ErrUserNotExist { if err != models.ErrUserNotExist {
ctx.Handle(500, "UserSignIn error: %v", err) ctx.Handle(500, "UserSignIn error: %v", err)
@ -160,7 +160,7 @@ func Http(ctx *middleware.Context) {
} }
} }
var f = func(rpc string, input []byte) { callback := func(rpc string, input []byte) {
if rpc == "receive-pack" { if rpc == "receive-pack" {
var lastLine int64 = 0 var lastLine int64 = 0
@ -189,6 +189,7 @@ func Http(ctx *middleware.Context) {
newCommitId := fields[1] newCommitId := fields[1]
refName := fields[2] refName := fields[2]
// FIXME: handle error.
models.Update(refName, oldCommitId, newCommitId, authUsername, username, reponame, authUser.Id) models.Update(refName, oldCommitId, newCommitId, authUsername, username, reponame, authUser.Id)
} }
lastLine = lastLine + size lastLine = lastLine + size
@ -199,25 +200,23 @@ func Http(ctx *middleware.Context) {
} }
} }
config := Config{setting.RepoRootPath, "git", true, true, f} HTTPBackend(&Config{
RepoRootPath: setting.RepoRootPath,
GitBinPath: "git",
UploadPack: true,
ReceivePack: true,
OnSucceed: callback,
})(ctx.Resp, ctx.Req.Request)
handler := HttpBackend(&config)
handler(ctx.Resp, ctx.Req.Request)
runtime.GC() runtime.GC()
} }
type route struct {
cr *regexp.Regexp
method string
handler func(handler)
}
type Config struct { type Config struct {
ReposRoot string RepoRootPath string
GitBinPath string GitBinPath string
UploadPack bool UploadPack bool
ReceivePack bool ReceivePack bool
OnSucceed func(rpc string, input []byte) OnSucceed func(rpc string, input []byte)
} }
type handler struct { type handler struct {
@ -228,6 +227,12 @@ type handler struct {
File string File string
} }
type route struct {
cr *regexp.Regexp
method string
handler func(handler)
}
var routes = []route{ var routes = []route{
{regexp.MustCompile("(.*?)/git-upload-pack$"), "POST", serviceUploadPack}, {regexp.MustCompile("(.*?)/git-upload-pack$"), "POST", serviceUploadPack},
{regexp.MustCompile("(.*?)/git-receive-pack$"), "POST", serviceReceivePack}, {regexp.MustCompile("(.*?)/git-receive-pack$"), "POST", serviceReceivePack},
@ -243,7 +248,7 @@ var routes = []route{
} }
// Request handling function // Request handling function
func HttpBackend(config *Config) http.HandlerFunc { func HTTPBackend(config *Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
for _, route := range routes { for _, route := range routes {
r.URL.Path = strings.ToLower(r.URL.Path) // blue: In case some repo name has upper case name r.URL.Path = strings.ToLower(r.URL.Path) // blue: In case some repo name has upper case name
@ -285,8 +290,7 @@ func serviceReceivePack(hr handler) {
func serviceRpc(rpc string, hr handler) { func serviceRpc(rpc string, hr handler) {
w, r, dir := hr.w, hr.r, hr.Dir w, r, dir := hr.w, hr.r, hr.Dir
access := hasAccess(r, hr.Config, dir, rpc, true) if !hasAccess(r, hr.Config, dir, rpc, true) {
if access == false {
renderNoAccess(w) renderNoAccess(w)
return return
} }
@ -337,7 +341,6 @@ func serviceRpc(rpc string, hr handler) {
if hr.Config.OnSucceed != nil { if hr.Config.OnSucceed != nil {
hr.Config.OnSucceed(rpc, input) hr.Config.OnSucceed(rpc, input)
} }
w.WriteHeader(http.StatusOK)
} }
func getInfoRefs(hr handler) { func getInfoRefs(hr handler) {
@ -408,7 +411,7 @@ func sendFile(contentType string, hr handler) {
} }
func getGitDir(config *Config, fPath string) (string, error) { func getGitDir(config *Config, fPath string) (string, error) {
root := config.ReposRoot root := config.RepoRootPath
if root == "" { if root == "" {
cwd, err := os.Getwd() cwd, err := os.Getwd()

8
routers/repo/issue.go

@ -270,12 +270,12 @@ func CreateIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) {
} }
act := &models.Action{ act := &models.Action{
ActUserId: ctx.User.Id, ActUserID: ctx.User.Id,
ActUserName: ctx.User.Name, ActUserName: ctx.User.Name,
ActEmail: ctx.User.Email, ActEmail: ctx.User.Email,
OpType: models.CREATE_ISSUE, OpType: models.CREATE_ISSUE,
Content: fmt.Sprintf("%d|%s", issue.Index, issue.Name), Content: fmt.Sprintf("%d|%s", issue.Index, issue.Name),
RepoId: ctx.Repo.Repository.Id, RepoID: ctx.Repo.Repository.Id,
RepoUserName: ctx.Repo.Owner.Name, RepoUserName: ctx.Repo.Owner.Name,
RepoName: ctx.Repo.Repository.Name, RepoName: ctx.Repo.Repository.Name,
RefName: ctx.Repo.BranchName, RefName: ctx.Repo.BranchName,
@ -845,12 +845,12 @@ func Comment(ctx *middleware.Context) {
// Notify watchers. // Notify watchers.
act := &models.Action{ act := &models.Action{
ActUserId: ctx.User.Id, ActUserID: ctx.User.Id,
ActUserName: ctx.User.LowerName, ActUserName: ctx.User.LowerName,
ActEmail: ctx.User.Email, ActEmail: ctx.User.Email,
OpType: models.COMMENT_ISSUE, OpType: models.COMMENT_ISSUE,
Content: fmt.Sprintf("%d|%s", issue.Index, strings.Split(content, "\n")[0]), Content: fmt.Sprintf("%d|%s", issue.Index, strings.Split(content, "\n")[0]),
RepoId: ctx.Repo.Repository.Id, RepoID: ctx.Repo.Repository.Id,
RepoUserName: ctx.Repo.Owner.LowerName, RepoUserName: ctx.Repo.Owner.LowerName,
RepoName: ctx.Repo.Repository.LowerName, RepoName: ctx.Repo.Repository.LowerName,
} }

12
routers/repo/repo.go

@ -181,7 +181,7 @@ func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) {
} }
} }
// Remote address can be HTTPS URL or local path. // Remote address can be HTTP/HTTPS URL or local path.
remoteAddr := form.CloneAddr remoteAddr := form.CloneAddr
if strings.HasPrefix(form.CloneAddr, "http") { if strings.HasPrefix(form.CloneAddr, "http") {
u, err := url.Parse(form.CloneAddr) u, err := url.Parse(form.CloneAddr)
@ -190,8 +190,8 @@ func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) {
ctx.RenderWithErr(ctx.Tr("form.url_error"), MIGRATE, &form) ctx.RenderWithErr(ctx.Tr("form.url_error"), MIGRATE, &form)
return return
} }
if len(form.AuthUserName) > 0 || len(form.AuthPasswd) > 0 { if len(form.AuthUsername) > 0 || len(form.AuthPassword) > 0 {
u.User = url.UserPassword(form.AuthUserName, form.AuthPasswd) u.User = url.UserPassword(form.AuthUsername, form.AuthPassword)
} }
remoteAddr = u.String() remoteAddr = u.String()
} else if !com.IsDir(remoteAddr) { } else if !com.IsDir(remoteAddr) {
@ -251,7 +251,7 @@ func Fork(ctx *middleware.Context) {
ctx.Data["Title"] = ctx.Tr("new_fork") ctx.Data["Title"] = ctx.Tr("new_fork")
if _, err := getForkRepository(ctx); err != nil { if _, err := getForkRepository(ctx); err != nil {
if err == models.ErrRepoNotExist { if models.IsErrRepoNotExist(err) {
ctx.Redirect(setting.AppSubUrl + "/") ctx.Redirect(setting.AppSubUrl + "/")
} else { } else {
ctx.Handle(500, "getForkRepository", err) ctx.Handle(500, "getForkRepository", err)
@ -275,7 +275,7 @@ func ForkPost(ctx *middleware.Context, form auth.CreateRepoForm) {
forkRepo, err := getForkRepository(ctx) forkRepo, err := getForkRepository(ctx)
if err != nil { if err != nil {
if err == models.ErrRepoNotExist { if models.IsErrRepoNotExist(err) {
ctx.Redirect(setting.AppSubUrl + "/") ctx.Redirect(setting.AppSubUrl + "/")
} else { } else {
ctx.Handle(500, "getForkRepository", err) ctx.Handle(500, "getForkRepository", err)
@ -356,7 +356,7 @@ func Action(ctx *middleware.Context) {
ctx.Repo.Repository.Description = ctx.Query("desc") ctx.Repo.Repository.Description = ctx.Query("desc")
ctx.Repo.Repository.Website = ctx.Query("site") ctx.Repo.Repository.Website = ctx.Query("site")
err = models.UpdateRepository(ctx.Repo.Repository) err = models.UpdateRepository(ctx.Repo.Repository, false)
} }
if err != nil { if err != nil {

3
routers/repo/setting.go

@ -78,8 +78,9 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) {
} }
ctx.Repo.Repository.Description = form.Description ctx.Repo.Repository.Description = form.Description
ctx.Repo.Repository.Website = form.Website ctx.Repo.Repository.Website = form.Website
visibilityChanged := ctx.Repo.Repository.IsPrivate != form.Private
ctx.Repo.Repository.IsPrivate = form.Private ctx.Repo.Repository.IsPrivate = form.Private
if err := models.UpdateRepository(ctx.Repo.Repository); err != nil { if err := models.UpdateRepository(ctx.Repo.Repository, visibilityChanged); err != nil {
ctx.Handle(404, "UpdateRepository", err) ctx.Handle(404, "UpdateRepository", err)
return return
} }

6
routers/repo/view.go

@ -141,13 +141,17 @@ func Home(ctx *middleware.Context) {
ctx.Handle(500, "GetSubModule", err) ctx.Handle(500, "GetSubModule", err)
return return
} }
smUrl := ""
if sm != nil {
smUrl = sm.Url
}
c, err := ctx.Repo.Commit.GetCommitOfRelPath(filepath.Join(treePath, te.Name())) c, err := ctx.Repo.Commit.GetCommitOfRelPath(filepath.Join(treePath, te.Name()))
if err != nil { if err != nil {
ctx.Handle(500, "GetCommitOfRelPath", err) ctx.Handle(500, "GetCommitOfRelPath", err)
return return
} }
files = append(files, []interface{}{te, git.NewSubModuleFile(c, sm.Url, te.Id.String())}) files = append(files, []interface{}{te, git.NewSubModuleFile(c, smUrl, te.Id.String())})
} }
} }
ctx.Data["Files"] = files ctx.Data["Files"] = files

15
routers/user/home.go

@ -104,7 +104,7 @@ func Dashboard(ctx *middleware.Context) {
for _, act := range actions { for _, act := range actions {
if act.IsPrivate { if act.IsPrivate {
// This prevents having to retrieve the repository for each action // This prevents having to retrieve the repository for each action
repo := &models.Repository{Id: act.RepoId, IsPrivate: true} repo := &models.Repository{Id: act.RepoID, IsPrivate: true}
if act.RepoUserName != ctx.User.LowerName { if act.RepoUserName != ctx.User.LowerName {
if has, _ := models.HasAccess(ctx.User, repo, models.ACCESS_MODE_READ); !has { if has, _ := models.HasAccess(ctx.User, repo, models.ACCESS_MODE_READ); !has {
continue continue
@ -216,7 +216,7 @@ func Profile(ctx *middleware.Context) {
continue continue
} }
// This prevents having to retrieve the repository for each action // This prevents having to retrieve the repository for each action
repo := &models.Repository{Id: act.RepoId, IsPrivate: true} repo := &models.Repository{Id: act.RepoID, IsPrivate: true}
if act.RepoUserName != ctx.User.LowerName { if act.RepoUserName != ctx.User.LowerName {
if has, _ := models.HasAccess(ctx.User, repo, models.ACCESS_MODE_READ); !has { if has, _ := models.HasAccess(ctx.User, repo, models.ACCESS_MODE_READ); !has {
continue continue
@ -261,8 +261,10 @@ func Email2User(ctx *middleware.Context) {
ctx.Redirect(setting.AppSubUrl + "/user/" + u.Name) ctx.Redirect(setting.AppSubUrl + "/user/" + u.Name)
} }
func Issues(ctx *middleware.Context) { func Issues(ctx *middleware.Context) {
ctx.Data["Title"] = "Your Issues" ctx.Data["Title"] = ctx.Tr("issues")
ctx.Data["PageIsDashboard"] = true
ctx.Data["PageIsIssues"] = true
viewType := ctx.Query("type") viewType := ctx.Query("type")
types := []string{"assigned", "created_by"} types := []string{"assigned", "created_by"}
@ -354,7 +356,7 @@ func Issues(ctx *middleware.Context) {
issues[i].Repo, err = models.GetRepositoryById(issues[i].RepoId) issues[i].Repo, err = models.GetRepositoryById(issues[i].RepoId)
if err != nil { if err != nil {
if err == models.ErrRepoNotExist { if models.IsErrRepoNotExist(err) {
log.Warn("user.Issues(GetRepositoryById #%d): repository not exist", issues[i].RepoId) log.Warn("user.Issues(GetRepositoryById #%d): repository not exist", issues[i].RepoId)
continue continue
} else { } else {
@ -386,5 +388,8 @@ func Issues(ctx *middleware.Context) {
} else { } else {
ctx.Data["ShowCount"] = issueStats.OpenCount ctx.Data["ShowCount"] = issueStats.OpenCount
} }
ctx.Data["ContextUser"] = ctx.User
ctx.HTML(200, ISSUES) ctx.HTML(200, ISSUES)
} }

17
routers/user/setting.go

@ -218,7 +218,7 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) {
if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
log.Error(4, "Set cache(MailResendLimit) fail: %v", err) log.Error(4, "Set cache(MailResendLimit) fail: %v", err)
} }
ctx.Flash.Success(ctx.Tr("settings.add_email_success_confirmation_email_sent")) ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", cleanEmail, setting.Service.ActiveCodeLives/60))
} else { } else {
ctx.Flash.Success(ctx.Tr("settings.add_email_success")) ctx.Flash.Success(ctx.Tr("settings.add_email_success"))
} }
@ -451,20 +451,13 @@ func SettingsDelete(ctx *middleware.Context) {
ctx.Data["PageIsSettingsDelete"] = true ctx.Data["PageIsSettingsDelete"] = true
if ctx.Req.Method == "POST" { if ctx.Req.Method == "POST" {
// tmpUser := models.User{ // FIXME: validate password.
// Passwd: ctx.Query("password"),
// Salt: ctx.User.Salt,
// }
// tmpUser.EncodePasswd()
// if tmpUser.Passwd != ctx.User.Passwd {
// ctx.Flash.Error("Password is not correct. Make sure you are owner of this account.")
// } else {
if err := models.DeleteUser(ctx.User); err != nil { if err := models.DeleteUser(ctx.User); err != nil {
switch err { switch {
case models.ErrUserOwnRepos: case models.IsErrUserOwnRepos(err):
ctx.Flash.Error(ctx.Tr("form.still_own_repo")) ctx.Flash.Error(ctx.Tr("form.still_own_repo"))
ctx.Redirect(setting.AppSubUrl + "/user/settings/delete") ctx.Redirect(setting.AppSubUrl + "/user/settings/delete")
case models.ErrUserHasOrgs: case models.IsErrUserHasOrgs(err):
ctx.Flash.Error(ctx.Tr("form.still_has_org")) ctx.Flash.Error(ctx.Tr("form.still_has_org"))
ctx.Redirect(setting.AppSubUrl + "/user/settings/delete") ctx.Redirect(setting.AppSubUrl + "/user/settings/delete")
default: default:

12
scripts/init/centos/gogs

@ -28,7 +28,6 @@ GOGS_HOME=/home/git/gogs
GOGS_PATH=${GOGS_HOME}/$NAME GOGS_PATH=${GOGS_HOME}/$NAME
GOGS_USER=git GOGS_USER=git
SERVICENAME="Gogs Go Git Service" SERVICENAME="Gogs Go Git Service"
PID=/var/run/$NAME.pid
LOCKFILE=/var/lock/subsys/gogs LOCKFILE=/var/lock/subsys/gogs
LOGFILE=${GOGS_HOME}/log/gogs.log LOGFILE=${GOGS_HOME}/log/gogs.log
RETVAL=0 RETVAL=0
@ -39,7 +38,7 @@ RETVAL=0
# Don't do anything if nothing is installed # Don't do anything if nothing is installed
[ -x ${GOGS_PATH} ] || exit 0 [ -x ${GOGS_PATH} ] || exit 0
DAEMON_OPTS="" DAEMON_OPTS="--check $NAME"
# Set additional options, if any # Set additional options, if any
[ ! -z "$GOGS_USER" ] && DAEMON_OPTS="$DAEMON_OPTS --user=${GOGS_USER}" [ ! -z "$GOGS_USER" ] && DAEMON_OPTS="$DAEMON_OPTS --user=${GOGS_USER}"
@ -47,8 +46,7 @@ DAEMON_OPTS=""
start() { start() {
cd ${GOGS_HOME} cd ${GOGS_HOME}
echo -n "Starting ${SERVICENAME}: " echo -n "Starting ${SERVICENAME}: "
daemon $DAEMON_OPTS --pidfile=${PID} "${GOGS_PATH} web 2>&1 > ${LOGFILE} &" daemon $DAEMON_OPTS "${GOGS_PATH} web > ${LOGFILE} 2>&1 &"
echo $! > ${PID}
RETVAL=$? RETVAL=$?
echo echo
[ $RETVAL = 0 ] && touch ${LOCKFILE} [ $RETVAL = 0 ] && touch ${LOCKFILE}
@ -59,10 +57,10 @@ start() {
stop() { stop() {
cd ${GOGS_HOME} cd ${GOGS_HOME}
echo -n "Shutting down ${SERVICENAME}: " echo -n "Shutting down ${SERVICENAME}: "
killproc -p ${PID} ${NAME} killproc ${NAME}
RETVAL=$? RETVAL=$?
echo echo
[ $RETVAL = 0 ] && rm -f ${LOCKFILE} ${PID} [ $RETVAL = 0 ] && rm -f ${LOCKFILE}
} }
case "$1" in case "$1" in
@ -74,7 +72,7 @@ case "$1" in
stop stop
;; ;;
status) status)
status -p ${PID} ${NAME} status ${NAME}
;; ;;
restart) restart)
stop stop

2
templates/.VERSION

@ -1 +1 @@
0.5.16.0301 Beta 0.6.0.0319 Beta

2
templates/admin/auth/edit.tmpl

@ -12,7 +12,7 @@
<div class="panel-header"> <div class="panel-header">
<strong>{{.i18n.Tr "admin.auths.edit"}}</strong> <strong>{{.i18n.Tr "admin.auths.edit"}}</strong>
</div> </div>
<form class="form form-align panel-body" id="auth-setting-form" action="{{AppSubUrl}}/admin/auths/{{.Source.Id}}" data-delete-url="/admin/auths/{{.Source.Id}}/delete" method="post"> <form class="form form-align panel-body" id="auth-setting-form" action="{{AppSubUrl}}/admin/auths/{{.Source.Id}}" data-delete-url="{{AppSubUrl}}/admin/auths/{{.Source.Id}}/delete" method="post">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<input type="hidden" value="{{.Source.Id}}" name="id"/> <input type="hidden" value="{{.Source.Id}}" name="id"/>
{{$type := .Source.Type}} {{$type := .Source.Type}}

2
templates/admin/user/edit.tmpl

@ -12,7 +12,7 @@
<div class="panel-header"> <div class="panel-header">
<strong>{{.i18n.Tr "admin.users.edit_account"}}</strong> <strong>{{.i18n.Tr "admin.users.edit_account"}}</strong>
</div> </div>
<form class="form form-align panel-body" id="user-profile-form" action="{{AppSubUrl}}/admin/users/{{.User.Id}}" method="post" data-delete-url="/admin/users/{{.User.Id}}/delete"> <form class="form form-align panel-body" id="user-profile-form" action="{{AppSubUrl}}/admin/users/{{.User.Id}}" method="post" data-delete-url="{{AppSubUrl}}/admin/users/{{.User.Id}}/delete">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<div class="field"> <div class="field">
<label class="req">{{.i18n.Tr "admin.users.auth_source"}}</label> <label class="req">{{.i18n.Tr "admin.users.auth_source"}}</label>

6
templates/ng/base/alert.tmpl

@ -1,3 +1,3 @@
{{if .Flash.ErrorMsg}}<span class="alert alert-red alert-radius block text-bold"><i class="octicon octicon-alert"></i>{{.Flash.ErrorMsg}}</span>{{end}} {{if .Flash.ErrorMsg}}<span class="alert alert-red alert-radius block text-bold"><i class="octicon octicon-alert"></i>{{.Flash.ErrorMsg|Str2html}}</span>{{end}}
{{if .Flash.SuccessMsg}}<div class="alert alert-green alert-radius block"><i class="octicon octicon-check"></i>{{.Flash.SuccessMsg}}</div>{{end}} {{if .Flash.SuccessMsg}}<div class="alert alert-green alert-radius block"><i class="octicon octicon-check"></i>{{.Flash.SuccessMsg|Str2html}}</div>{{end}}
{{if .Flash.InfoMsg}}<div class="alert alert-blue alert-radius block"><i class="octicon octicon-info"></i>{{.Flash.InfoMsg}}</div>{{end}} {{if .Flash.InfoMsg}}<div class="alert alert-blue alert-radius block"><i class="octicon octicon-info"></i>{{.Flash.InfoMsg|Str2html}}</div>{{end}}

2
templates/repo/bare.tmpl

@ -25,7 +25,7 @@
<button class="btn btn-gray left" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">HTTPS</button> <button class="btn btn-gray left" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">HTTPS</button>
<input id="repo-clone-url" type="text" class="ipt ipt-disabled left" value="{{.CloneLink.SSH}}" onclick="this.select()" readonly /> <input id="repo-clone-url" type="text" class="ipt ipt-disabled left" value="{{.CloneLink.SSH}}" onclick="this.select()" readonly />
<button class="btn btn-black left btn-right-radius" id="repo-clone-copy" data-copy-val="val" data-copy-from="#repo-clone-url">{{.i18n.Tr "repo.copy_link"}}</button> <button class="btn btn-black left btn-right-radius" id="repo-clone-copy" data-copy-val="val" data-copy-from="#repo-clone-url">{{.i18n.Tr "repo.copy_link"}}</button>
<p class="text-center" id="repo-clone-help">{{.i18n.Tr "repo.clone_helper" | Str2html}}</p> <p class="text-center" id="repo-clone-help">{{.i18n.Tr "repo.clone_helper" "http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository" | Str2html}}</p>
<hr/> <hr/>
</div> </div>
<div id="repo-bare-cmd" class="text-center"> <div id="repo-bare-cmd" class="text-center">

4
templates/repo/migrate.tmpl

@ -68,8 +68,8 @@
<span>{{.i18n.Tr "repo.migrate_type_helper" | Str2html}}</span> <span>{{.i18n.Tr "repo.migrate_type_helper" | Str2html}}</span>
</div> </div>
<div class="field clear"> <div class="field clear">
<label class="left" for="desc">{{.i18n.Tr "repo.repo_desc"}}</label> <label class="left" for="description">{{.i18n.Tr "repo.repo_desc"}}</label>
<textarea class="ipt ipt-large ipt-radius {{if .Err_Description}}ipt-error{{end}}" id="desc" name="desc">{{.desc}}</textarea> <textarea class="ipt ipt-large ipt-radius {{if .Err_Description}}ipt-error{{end}}" id="description" name="description">{{.description}}</textarea>
</div> </div>
<div class="field"> <div class="field">
<label for="repo-create-submit"></label> <label for="repo-create-submit"></label>

4
templates/repo/view_list.tmpl

@ -39,7 +39,11 @@
<span class="octicon octicon-file-submodule"></span> <span class="octicon octicon-file-submodule"></span>
</td> </td>
<td class="name"> <td class="name">
{{if $commit.RefUrl}}
<a href="{{$commit.RefUrl}}" class="text-truncate">{{$entry.Name}}</a> @ <a href="{{$commit.RefUrl}}/commit/{{$commit.RefId}}">{{ShortSha $commit.RefId}}</a> <a href="{{$commit.RefUrl}}" class="text-truncate">{{$entry.Name}}</a> @ <a href="{{$commit.RefUrl}}/commit/{{$commit.RefId}}">{{ShortSha $commit.RefId}}</a>
{{else}}
{{$entry.Name}} @ {{ShortSha $commit.RefId}}
{{end}}
</td> </td>
{{else}} {{else}}
<td class="icon"> <td class="icon">

14
templates/user/dashboard/feeds.tmpl

@ -7,19 +7,19 @@
<p class="text-bold"> <p class="text-bold">
<a href="{{AppSubUrl}}/{{.GetActUserName}}">{{.GetActUserName}}</a> <a href="{{AppSubUrl}}/{{.GetActUserName}}">{{.GetActUserName}}</a>
{{if eq .GetOpType 1}} {{if eq .GetOpType 1}}
{{$.i18n.Tr "action.create_repo" AppSubUrl .GetRepoLink .GetRepoLink | Str2html}} {{$.i18n.Tr "action.create_repo" .GetRepoLink .GetRepoPath | Str2html}}
{{else if eq .GetOpType 5}} {{else if eq .GetOpType 5}}
{{$.i18n.Tr "action.commit_repo" AppSubUrl .GetRepoLink .GetBranch .GetBranch AppSubUrl .GetRepoLink .GetRepoLink | Str2html}} {{$.i18n.Tr "action.commit_repo" .GetRepoLink .GetBranch .GetRepoPath | Str2html}}
{{else if eq .GetOpType 6}} {{else if eq .GetOpType 6}}
{{ $index := index .GetIssueInfos 0}} {{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.create_issue" .GetRepoLink $index | Str2html}} {{$.i18n.Tr "action.create_issue" .GetRepoLink $index .GetRepoPath | Str2html}}
{{else if eq .GetOpType 8}} {{else if eq .GetOpType 8}}
{{$.i18n.Tr "action.transfer_repo" .GetContent AppSubUrl .GetRepoLink .GetRepoLink | Str2html}} {{$.i18n.Tr "action.transfer_repo" .GetContent .GetRepoLink .GetRepoPath | Str2html}}
{{else if eq .GetOpType 9}} {{else if eq .GetOpType 9}}
{{$.i18n.Tr "action.push_tag" AppSubUrl .GetRepoLink .GetBranch .GetBranch AppSubUrl .GetRepoLink .GetRepoLink | Str2html}} {{$.i18n.Tr "action.push_tag" .GetRepoLink .GetBranch .GetRepoPath | Str2html}}
{{else if eq .GetOpType 10}} {{else if eq .GetOpType 10}}
{{ $index := index .GetIssueInfos 0}} {{ $index := index .GetIssueInfos 0}}
{{$.i18n.Tr "action.comment_issue" .GetRepoLink $index | Str2html}} {{$.i18n.Tr "action.comment_issue" .GetRepoLink $index .GetRepoPath | Str2html}}
{{end}} {{end}}
</p> </p>
{{if eq .GetOpType 5}} {{if eq .GetOpType 5}}
@ -28,7 +28,7 @@
{{ $push := ActionContent2Commits .}} {{ $push := ActionContent2Commits .}}
{{ $repoLink := .GetRepoLink}} {{ $repoLink := .GetRepoLink}}
{{range $push.Commits}} {{range $push.Commits}}
<li><img class="avatar-16" src="{{AvatarLink .AuthorEmail}}?s=16"> <a href="{{AppSubUrl}}/{{$repoLink}}/commit/{{.Sha1}}">{{ShortSha .Sha1}}</a> <span class="text-truncate grid-4-5">{{.Message}}</span></li> <li><img class="avatar-16" src="{{AvatarLink .AuthorEmail}}?s=16"> <a href="{{$repoLink}}/commit/{{.Sha1}}">{{ShortSha .Sha1}}</a> <span class="text-truncate grid-4-5">{{.Message}}</span></li>
{{end}} {{end}}
{{if $push.CompareUrl}}<li><a href="{{$push.CompareUrl}}">{{$.i18n.Tr "action.compare_2_commits"}} »</a></li>{{end}} {{if $push.CompareUrl}}<li><a href="{{$push.CompareUrl}}">{{$.i18n.Tr "action.compare_2_commits"}} »</a></li>{{end}}
</ul> </ul>

95
templates/user/issues.tmpl

@ -1,53 +1,44 @@
{{template "base/head" .}} {{template "ng/base/head" .}}
{{template "base/navbar" .}} {{template "ng/base/header" .}}
<div id="body-nav"> {{template "user/dashboard/nav" .}}
<div class="container"> <div id="dashboard-wrapper">
<ul class="nav nav-pills pull-right"> <div id="dashboard" class="container" data-page="user">
<li><a href="{{AppSubUrl}}/">News Feed</a></li> {{if .HasInfo}}<div class="alert alert-info">{{.InfoMsg}}</div>{{end}}
<li class="active"><a href="{{AppSubUrl}}/issues">Issues</a></li> <div id="issue">
<!-- <li><a href="{{AppSubUrl}}/pulls">Pull Requests</a></li> <div class="left grid-1-5 filter-list">
<li><a href="{{AppSubUrl}}/stars">Stars</a></li> --> <ul class="list-unstyled menu menu-vertical">
</ul> <li><a href="{{AppSubUrl}}/issues?state={{.State}}&repoid={{.RepoId}}" class="radius{{if eq .ViewType "all"}} active{{end}}" >In your repositories <strong class="pull-right">{{.IssueStats.AllCount}}</strong></a></li>
<h3>Your Issues</h3> <li><a href="{{AppSubUrl}}/issues?type=assigned&repoid={{.RepoId}}&state={{.State}}" class="radius{{if eq .ViewType "assigned"}} active{{end}}">Assigned to you <strong class="pull-right">{{.IssueStats.AssignCount}}</strong></a></li>
</div> <li><a href="{{AppSubUrl}}/issues?type=created_by&repoid={{.RepoId}}&state={{.State}}" class="radius{{if eq .ViewType "created_by"}} active{{end}}">Created by you <strong class="pull-right">{{.IssueStats.CreateCount}}</strong></a></li>
<li><hr/></li>
{{range .Repos}}
<li><a href="{{AppSubUrl}}/issues?type={{$.ViewType}}{{if eq $.RepoId .Id}}{{else}}&repoid={{.Id}}{{end}}&state={{$.State}}" class="radius{{if eq $.RepoId .Id}} active{{end}}">{{$.SignedUser.Name}}/{{.Name}} <strong class="pull-right">{{if $.IsShowClosed}}{{.NumClosedIssues}}{{else}}{{.NumOpenIssues}}{{end}}</strong></a></li>
{{end}}
</ul>
</div>
<div class="right grid-3-4">
<div class="filter-option">
<div class="btn-group">
<a class="btn btn-white btn-small issue-open{{if not .IsShowClosed}} active{{end}}" href="{{AppSubUrl}}/issues?type={{.ViewType}}&repoid={{.RepoId}}">Open</a>
<a class="btn btn-white btn-small issue-close{{if .IsShowClosed}} active{{end}}" href="{{AppSubUrl}}/issues?type={{.ViewType}}&repoid={{.RepoId}}&state=closed">Closed</a>
</div>
</div>
<div class="issues list-group">
{{range .Issues}}{{if .}}
<div class="list-group-item issue-item" id="issue-{{.Id}}" onclick="window.location.href='{{AppSubUrl}}/{{.Repo.Owner.Name}}/{{.Repo.Name}}/issues/{{.Index}}'">
<span class="number pull-right">#{{.Index}}</span>
<h5 class="title"><a href="{{AppSubUrl}}/{{.Repo.Owner.Name}}/{{.Repo.Name}}/issues/{{.Index}}">{{.Name}}</a></h5>
<p class="info">
<span class="author"><img class="avatar" src="{{.Poster.AvatarLink}}" alt="" width="20"/>
<a href="{{AppSubUrl}}/{{.Poster.Name}}">{{.Poster.Name}}</a></span>
<span class="time">{{TimeSince .Created $.Lang}}</span>
<span class="comment"><i class="fa fa-comments"></i> {{.NumComments}}</span>
</p>
</div>
{{end}}{{end}}
</div>
</div>
</div>
</div>
</div> </div>
{{template "ng/base/footer" .}}
<div id="body" class="container" data-page="user">
{{if .HasInfo}}<div class="alert alert-info">{{.InfoMsg}}</div>{{end}}
<div id="issue">
<div class="col-md-3 filter-list">
<ul class="list-unstyled">
<li><a href="{{AppSubUrl}}/issues?state={{.State}}&repoid={{.RepoId}}"{{if eq .ViewType "all"}} class="active"{{end}}>In your repositories <strong class="pull-right">{{.IssueStats.AllCount}}</strong></a></li>
<li><a href="{{AppSubUrl}}/issues?type=assigned&repoid={{.RepoId}}&state={{.State}}"{{if eq .ViewType "assigned"}} class="active"{{end}}>Assigned to you <strong class="pull-right">{{.IssueStats.AssignCount}}</strong></a></li>
<li><a href="{{AppSubUrl}}/issues?type=created_by&repoid={{.RepoId}}&state={{.State}}"{{if eq .ViewType "created_by"}} class="active"{{end}}>Created by you <strong class="pull-right">{{.IssueStats.CreateCount}}</strong></a></li>
<li><hr/></li>
{{range .Repos}}
<li><a href="{{AppSubUrl}}/issues?type={{$.ViewType}}{{if eq $.RepoId .Id}}{{else}}&repoid={{.Id}}{{end}}&state={{$.State}}" class="sm{{if eq $.RepoId .Id}} active{{end}}">{{$.SignedUser.Name}}/{{.Name}} <strong class="pull-right">{{if $.IsShowClosed}}{{.NumClosedIssues}}{{else}}{{.NumOpenIssues}}{{end}}</strong></a></li>
{{end}}
</ul>
</div>
<div class="col-md-9">
<div class="filter-option">
<div class="btn-group">
<a class="btn btn-default issue-open{{if not .IsShowClosed}} active{{end}}" href="{{AppSubUrl}}/issues?type={{.ViewType}}&repoid={{.RepoId}}">Open</a>
<a class="btn btn-default issue-close{{if .IsShowClosed}} active{{end}}" href="{{AppSubUrl}}/issues?type={{.ViewType}}&repoid={{.RepoId}}&state=closed">Closed</a>
</div>
</div>
<div class="issues list-group">
{{range .Issues}}{{if .}}
<div class="list-group-item issue-item" id="issue-{{.Id}}">
<span class="number pull-right">#{{.Index}}</span>
<h5 class="title"><a href="{{AppSubUrl}}/{{.Repo.Owner.Name}}/{{.Repo.Name}}/issues/{{.Index}}">{{.Name}}</a></h5>
<p class="info">
<span class="author"><img class="avatar" src="{{.Poster.AvatarLink}}" alt="" width="20"/>
<a href="{{AppSubUrl}}/{{.Poster.Name}}">{{.Poster.Name}}</a></span>
<span class="time">{{TimeSince .Created $.Lang}}</span>
<span class="comment"><i class="fa fa-comments"></i> {{.NumComments}}</span>
</p>
</div>
{{end}}{{end}}
</div>
</div>
</div>
</div>
{{template "base/footer" .}}

1
wercker.yml

@ -1 +0,0 @@
box: wercker/default
Loading…
Cancel
Save