mirror of
https://github.com/gogs/gogs.git
synced 2026-03-02 10:11:04 +01:00
Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09c981846b | ||
|
|
037a01c4e4 | ||
|
|
1d95844d55 | ||
|
|
1c9dd11ba7 | ||
|
|
1e7e092992 | ||
|
|
33a99d587a | ||
|
|
9cd16c5b12 | ||
|
|
6673dcb038 | ||
|
|
71142929cc | ||
|
|
d7b924f17d | ||
|
|
b117befc2b | ||
|
|
7786cb76f3 | ||
|
|
eb918c2368 | ||
|
|
8ecbf0f16d | ||
|
|
b13caa23d9 | ||
|
|
fd79fad2ec | ||
|
|
19423957b1 | ||
|
|
3362b3a44f | ||
|
|
50264200f0 | ||
|
|
7436ce6403 | ||
|
|
91789930bc | ||
|
|
ea375c0dcc | ||
|
|
7509fa2c33 | ||
|
|
acdb4d8bdd | ||
|
|
95f9c85bcc | ||
|
|
79dcd7ee6e | ||
|
|
ed001d70e4 | ||
|
|
42a8c15ad0 | ||
|
|
9a27e5ccdc | ||
|
|
71123c816d | ||
|
|
168c69273f | ||
|
|
4df378b892 | ||
|
|
351dfc95a9 | ||
|
|
837155577a | ||
|
|
7e88420bc6 | ||
|
|
5911fc3512 | ||
|
|
4108c12092 | ||
|
|
e444a67d59 | ||
|
|
0cce4439ce | ||
|
|
59c965a5ec | ||
|
|
76bdbcc969 | ||
|
|
477b4d3b50 | ||
|
|
4d31eb2c0d | ||
|
|
d0b0d24f22 | ||
|
|
5d95ffe3eb | ||
|
|
98da7241a0 | ||
|
|
bc17f2f759 | ||
|
|
40f3142264 | ||
|
|
b21160a13a | ||
|
|
5b2afd8ec8 | ||
|
|
7a3eccc709 | ||
|
|
2a8d71367d | ||
|
|
3d5d61778a | ||
|
|
ddcc8d998c | ||
|
|
99e9bbef6c | ||
|
|
0e96a46020 | ||
|
|
df5ed64cca | ||
|
|
2a0bb1fa90 | ||
|
|
c6083c335e | ||
|
|
2e9c4ddedb | ||
|
|
fa8bf0f1d7 | ||
|
|
9a2e43bff2 | ||
|
|
bd5dc626e8 | ||
|
|
626dc1f0bd | ||
|
|
1b0ef0ec0b | ||
|
|
e4a092fb5a | ||
|
|
b886fb4bf0 | ||
|
|
fa5e372f75 | ||
|
|
356f1438a6 | ||
|
|
a19aaa439d | ||
|
|
0d469f261e | ||
|
|
c3440c4dd3 | ||
|
|
718d3ae258 | ||
|
|
b8d48bdb62 | ||
|
|
15d62bba82 | ||
|
|
eb6c634475 | ||
|
|
eec06fb3df | ||
|
|
df05134494 | ||
|
|
9bd3ebe207 | ||
|
|
a576224d0e | ||
|
|
989f30eb41 | ||
|
|
06d293a84e | ||
|
|
120cd4e471 | ||
|
|
1cbd4c01fb | ||
|
|
2528c482e9 | ||
|
|
b1a53f6d8e | ||
|
|
fde9c69679 | ||
|
|
3df5dcc1dc | ||
|
|
14080dd61d | ||
|
|
da2585c11e | ||
|
|
dd8a06a397 | ||
|
|
4e0c697aaf | ||
|
|
3ffbb54337 | ||
|
|
67cfb6735b | ||
|
|
b7508b06fa | ||
|
|
2a0db47935 | ||
|
|
dce2a9e7e1 | ||
|
|
abb02889f2 | ||
|
|
e2ca53029e |
28
.gopmfile
28
.gopmfile
@@ -3,7 +3,7 @@ path = github.com/gogits/gogs
|
||||
|
||||
[deps]
|
||||
github.com/bradfitz/gomemcache = commit:72a68649ba
|
||||
github.com/codegangsta/cli = commit:0302d39
|
||||
github.com/codegangsta/cli = commit:b5232bb
|
||||
github.com/go-macaron/binding = commit:2502aaf
|
||||
github.com/go-macaron/cache = commit:5617353
|
||||
github.com/go-macaron/captcha = commit:8aa5919
|
||||
@@ -16,32 +16,32 @@ github.com/go-macaron/toolbox = commit:ab30a81
|
||||
github.com/go-sql-driver/mysql = commit:d512f20
|
||||
github.com/go-xorm/core = commit:acb6f00
|
||||
github.com/go-xorm/xorm = commit:a8fba4d
|
||||
github.com/gogits/chardet = commit:2404f77725
|
||||
github.com/gogits/git-shell = commit:de77627
|
||||
github.com/gogits/go-gogs-client = commit:4b541fa
|
||||
github.com/gogits/git-module = commit:5cd57b9
|
||||
github.com/gogits/go-gogs-client = commit:78460e9
|
||||
github.com/issue9/identicon = commit:f8c0d2c
|
||||
github.com/klauspost/compress = commit:bcd0709
|
||||
github.com/klauspost/cpuid = commit:8d9fe96
|
||||
github.com/klauspost/crc32 = commit:0aff1ea
|
||||
github.com/kardianos/minwinsvc = commit:cad6b2b
|
||||
github.com/klauspost/compress = commit:f7ff951
|
||||
github.com/klauspost/cpuid = commit:ef30b90
|
||||
github.com/klauspost/crc32 = commit:41b6596
|
||||
github.com/lib/pq = commit:11fc39a
|
||||
github.com/mattn/go-sqlite3 = commit:5651a9d
|
||||
github.com/mcuadros/go-version = commit:d52711f
|
||||
github.com/microcosm-cc/bluemonday = commit:4ac6f27
|
||||
github.com/msteinert/pam = commit:02ccfbf
|
||||
github.com/nfnt/resize = commit:dc93e1b98c
|
||||
github.com/russross/blackfriday = commit:300106c
|
||||
github.com/russross/blackfriday = commit:d18b67a
|
||||
github.com/shurcooL/sanitized_anchor_name = commit:10ef21a
|
||||
github.com/Unknwon/cae = commit:7f5e046
|
||||
github.com/Unknwon/com = commit:28b053d
|
||||
github.com/Unknwon/i18n = commit:3b48b66
|
||||
github.com/Unknwon/paginater = commit:7748a72
|
||||
golang.org/x/net =
|
||||
golang.org/x/text =
|
||||
golang.org/x/crypto =
|
||||
golang.org/x/net = commit:28273ec
|
||||
golang.org/x/text = commit:cf49866
|
||||
golang.org/x/crypto = commit:f18420e
|
||||
gopkg.in/asn1-ber.v1 = commit:4e86f43
|
||||
gopkg.in/gomail.v2 = commit:df6fc79
|
||||
gopkg.in/ini.v1 = commit:65f8c74
|
||||
gopkg.in/ldap.v2 = e9a325d
|
||||
gopkg.in/gomail.v2 = commit:fbb71dd
|
||||
gopkg.in/ini.v1 = commit:77178f2
|
||||
gopkg.in/ldap.v2 = commit:e9a325d
|
||||
gopkg.in/macaron.v1 = commit:1c6dd87
|
||||
gopkg.in/redis.v2 = commit:e617904962
|
||||
|
||||
|
||||
@@ -24,4 +24,4 @@ before:
|
||||
- mv packager/.godir .
|
||||
after:
|
||||
- mv bin/main gogs
|
||||
after_install: ./packager/debian/postinst
|
||||
after_install: ./packager/hooks/postinst
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
|
||||
|
||||
@@ -42,13 +42,7 @@ There is no standard form of making a feature request. Just try to describe the
|
||||
|
||||
### Pull Request
|
||||
|
||||
Pull requests are always welcome, but note that **ALL PULL REQUESTS MUST APPLY TO THE `develop` BRANCH**.
|
||||
|
||||
We are always thrilled to receive pull requests, and do our best to process them as fast as possible. Not sure if that typo is worth a pull request? Do it! We will appreciate it.
|
||||
|
||||
If your pull request is not accepted on the first try, don't be discouraged! If there's a problem with the implementation, hopefully you received feedback on what to improve.
|
||||
|
||||
We're trying very hard to keep Gogs lean and focused. We don't want it to do everything for everybody. This means that we might decide against incorporating a new feature. We believe you do like to discuss with us first in [Gitter](https://gitter.im/gogits/gogs).
|
||||
Please read detailed information on [Wiki](https://github.com/gogits/gogs/wiki/Contributing-Code).
|
||||
|
||||
### Ask For Help
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -13,6 +13,8 @@ NOW = $(shell date -u '+%Y%m%d%I%M%S')
|
||||
|
||||
.PHONY: build pack release bindata clean
|
||||
|
||||
.IGNORE: public/css/gogs.css
|
||||
|
||||
build: $(GENERATED)
|
||||
go install -ldflags '$(LDFLAGS)' -tags '$(TAGS)'
|
||||
cp '$(GOPATH)/bin/gogs' .
|
||||
|
||||
18
README.md
18
README.md
@@ -1,11 +1,9 @@
|
||||
Gogs - Go Git Service [](https://travis-ci.org/gogits/gogs)
|
||||
Gogs - Go Git Service [](https://travis-ci.org/gogits/gogs) [](https://quay.io/repository/gogs/gogs) [](https://crowdin.com/project/gogs) [](https://gitter.im/gogits/gogs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
=====================
|
||||
|
||||
[](https://gitter.im/gogits/gogs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||

|
||||
|
||||

|
||||
|
||||
##### Current version: 0.7.33 Beta
|
||||
##### Current version: 0.8.10
|
||||
|
||||
| Web | UI | Preview |
|
||||
|:-------------:|:-------:|:-------:|
|
||||
@@ -15,10 +13,10 @@ Gogs - Go Git Service [ 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 `develop` branch.
|
||||
- :bangbang:<span style="color: red">You **MUST** read [CONTRIBUTING.md](CONTRIBUTING.md) before you start filing an issue or making a Pull Request, and **MUST** discuss with us on [Gitter](https://gitter.im/gogits/gogs) for UI changes, otherwise it's high possibilities that we are not going to merge it.</span>:bangbang:
|
||||
- :bangbang: You **MUST** read [CONTRIBUTING.md](CONTRIBUTING.md) for bug report and contributing code. :bangbang:
|
||||
- Please [start discussion](http://forum.gogs.io/category/2/general-discussion) or [ask a question](http://forum.gogs.io/category/4/getting-help) on [the forum](http://forum.gogs.io/). GitHub issue tracker only keeps **bugs** and **feature requests**, all other topics will be closed without reason.
|
||||
- Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) was reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site.
|
||||
- The demo site [try.gogs.io](https://try.gogs.io) is running under `develop` branch.
|
||||
- If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**. Thanks!
|
||||
- If you're interested in using APIs, we have experimental support with [documentation](https://github.com/gogits/go-gogs-client/wiki).
|
||||
- If your team/company is using Gogs and would like to put your logo on [our website](http://gogs.io), contact us by any means.
|
||||
@@ -46,7 +44,7 @@ The goal of this project is to make the easiest, fastest, and most painless way
|
||||
- Account/Organization/Repository management
|
||||
- Repository/Organization webhooks (including Slack)
|
||||
- Repository Git hooks/deploy keys
|
||||
- Repository issues and pull requests
|
||||
- Repository issues, pull requests and wiki
|
||||
- Add/Remove repository collaborators
|
||||
- Gravatar and custom source
|
||||
- Mail service
|
||||
@@ -87,7 +85,7 @@ There are 5 ways to install Gogs:
|
||||
|
||||
### Screencasts
|
||||
|
||||
- [Instalando Gogs no Ubuntu](http://blog.linuxpro.com.br/2015/08/14/instalando-gogs-no-ubuntu/) (Português)
|
||||
- [Instalando Gogs no Ubuntu](https://www.youtube.com/watch?v=4UkHAR1F7ZA) (Português)
|
||||
|
||||
### Deploy to Cloud
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
|
||||
|
||||
- 有关基本用法和变更日志,请通过 [使用手册](http://gogs.io/docs/intro/) 查看。
|
||||
- 您可以到 [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) 跟随开发团队的脚步。
|
||||
- 想要先睹为快?通过 [在线体验](https://try.gogs.io/gogs/gogs) 或查看 **安装部署 -> 二进制安装** 小节。
|
||||
- 想要先睹为快?直接去 [在线体验](https://try.gogs.io/gogs/gogs) 。
|
||||
- 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.html) 页面获取帮助。
|
||||
- 希望帮助多国语言界面的翻译吗?请立即访问 [详情页面](http://gogs.io/docs/features/i18n.html)!
|
||||
|
||||
@@ -24,7 +24,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
|
||||
- 支持用户、组织和仓库管理系统
|
||||
- 支持仓库和组织级别 Web 钩子(包括 Slack 集成)
|
||||
- 支持仓库 Git 钩子和部署密钥
|
||||
- 支持仓库工单(Issue)和合并请求(Pull Request)
|
||||
- 支持仓库工单(Issue)、合并请求(Pull Request)以及 Wiki
|
||||
- 支持添加和删除仓库协作者
|
||||
- 支持 Gravatar 以及自定义源
|
||||
- 支持邮件服务
|
||||
|
||||
@@ -14,11 +14,10 @@ import (
|
||||
)
|
||||
|
||||
var CmdCert = cli.Command{
|
||||
Name: "cert",
|
||||
Usage: "Generate self-signed certificate",
|
||||
Description: `Generate a self-signed X.509 certificate for a TLS server.
|
||||
Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
|
||||
Action: runCert,
|
||||
Name: "cert",
|
||||
Usage: "Generate self-signed certificate",
|
||||
Description: `Please use build tags "cert" to rebuild Gogs in order to have this ability`,
|
||||
Action: runCert,
|
||||
}
|
||||
|
||||
func runCert(ctx *cli.Context) {
|
||||
|
||||
13
cmd/serve.go
13
cmd/serve.go
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/codegangsta/cli"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/httplib"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
@@ -87,7 +88,7 @@ func fail(userMessage, logMessage string, args ...interface{}) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func handleUpdateTask(uuid string, user *models.User, username, reponame string, isWiki bool) {
|
||||
func handleUpdateTask(uuid string, user, repoUser *models.User, reponame string, isWiki bool) {
|
||||
task, err := models.GetUpdateTaskByUUID(uuid)
|
||||
if err != nil {
|
||||
if models.IsErrUpdateTaskNotExist(err) {
|
||||
@@ -104,13 +105,13 @@ func handleUpdateTask(uuid string, user *models.User, username, reponame string,
|
||||
}
|
||||
|
||||
if err = models.Update(task.RefName, task.OldCommitID, task.NewCommitID,
|
||||
user.Name, username, reponame, user.Id); err != nil {
|
||||
user.Name, repoUser.Name, reponame, user.Id); err != nil {
|
||||
log.GitLogger.Error(2, "Update: %v", err)
|
||||
}
|
||||
|
||||
// Ask for running deliver hook and test pull request tasks.
|
||||
reqURL := setting.AppUrl + username + "/" + reponame + "/tasks/trigger?branch=" +
|
||||
strings.TrimPrefix(task.RefName, "refs/heads/")
|
||||
reqURL := setting.LocalURL + repoUser.Name + "/" + reponame + "/tasks/trigger?branch=" +
|
||||
strings.TrimPrefix(task.RefName, "refs/heads/") + "&secret=" + base.EncodeMD5(repoUser.Salt)
|
||||
log.GitLogger.Trace("Trigger task: %s", reqURL)
|
||||
|
||||
resp, err := httplib.Head(reqURL).SetTLSClientConfig(&tls.Config{
|
||||
@@ -163,7 +164,7 @@ func runServ(c *cli.Context) {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
fail("Repository owner does not exist", "Unregistered owner: %s", username)
|
||||
}
|
||||
fail("Internal error", "Failed to get repository owner(%s): %v", username, err)
|
||||
fail("Internal error", "Failed to get repository owner (%s): %v", username, err)
|
||||
}
|
||||
|
||||
repo, err := models.GetRepositoryByName(repoUser.Id, reponame)
|
||||
@@ -266,7 +267,7 @@ func runServ(c *cli.Context) {
|
||||
}
|
||||
|
||||
if requestedMode == models.ACCESS_MODE_WRITE {
|
||||
handleUpdateTask(uuid, user, username, reponame, isWiki)
|
||||
handleUpdateTask(uuid, user, repoUser, reponame, isWiki)
|
||||
}
|
||||
|
||||
// Update user key activity.
|
||||
|
||||
18
cmd/web.go
18
cmd/web.go
@@ -29,6 +29,8 @@ import (
|
||||
"gopkg.in/ini.v1"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/avatar"
|
||||
@@ -78,18 +80,19 @@ func checkVersion() {
|
||||
// Check dependency version.
|
||||
checkers := []VerChecker{
|
||||
{"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.4.4.1029"},
|
||||
{"github.com/Unknwon/macaron", macaron.Version, "0.5.4"},
|
||||
{"github.com/go-macaron/binding", binding.Version, "0.1.0"},
|
||||
{"github.com/go-macaron/cache", cache.Version, "0.1.2"},
|
||||
{"github.com/go-macaron/csrf", csrf.Version, "0.0.3"},
|
||||
{"github.com/go-macaron/i18n", i18n.Version, "0.2.0"},
|
||||
{"github.com/go-macaron/session", session.Version, "0.1.6"},
|
||||
{"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"},
|
||||
{"gopkg.in/ini.v1", ini.Version, "1.3.4"},
|
||||
{"gopkg.in/ini.v1", ini.Version, "1.8.4"},
|
||||
{"gopkg.in/macaron.v1", macaron.Version, "0.8.0"},
|
||||
{"github.com/gogits/git-shell", git.Version, "0.2.1"},
|
||||
}
|
||||
for _, c := range checkers {
|
||||
if !version.Compare(c.Version(), c.Expected, ">=") {
|
||||
log.Fatal(4, "Package '%s' version is too old(%s -> %s), did you forget to update?", c.ImportPath, c.Version(), c.Expected)
|
||||
log.Fatal(4, "Package '%s' version is too old (%s -> %s), did you forget to update?", c.ImportPath, c.Version(), c.Expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -255,10 +258,8 @@ func runWeb(ctx *cli.Context) {
|
||||
|
||||
m.Group("/users", func() {
|
||||
m.Get("", admin.Users)
|
||||
m.Get("/new", admin.NewUser)
|
||||
m.Post("/new", bindIgnErr(auth.AdminCrateUserForm{}), admin.NewUserPost)
|
||||
m.Get("/:userid", admin.EditUser)
|
||||
m.Post("/:userid", bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
|
||||
m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(auth.AdminCrateUserForm{}), admin.NewUserPost)
|
||||
m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost)
|
||||
m.Post("/:userid/delete", admin.DeleteUser)
|
||||
})
|
||||
|
||||
@@ -273,8 +274,7 @@ func runWeb(ctx *cli.Context) {
|
||||
|
||||
m.Group("/auths", func() {
|
||||
m.Get("", admin.Authentications)
|
||||
m.Get("/new", admin.NewAuthSource)
|
||||
m.Post("/new", bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
|
||||
m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
|
||||
m.Combo("/:authid").Get(admin.EditAuthSource).
|
||||
Post(bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost)
|
||||
m.Post("/:authid/delete", admin.DeleteAuthSource)
|
||||
|
||||
20
conf/app.ini
20
conf/app.ini
@@ -15,6 +15,8 @@ SCRIPT_TYPE = bash
|
||||
ANSI_CHARSET =
|
||||
; Force every new repository to be private
|
||||
FORCE_PRIVATE = false
|
||||
; Global maximum creation limit of repository per user, -1 means no limit
|
||||
MAX_CREATION_LIMIT = -1
|
||||
; Patch test queue length, make it as large as possible
|
||||
PULL_REQUEST_QUEUE_LENGTH = 10000
|
||||
|
||||
@@ -46,6 +48,10 @@ DOMAIN = localhost
|
||||
ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/
|
||||
HTTP_ADDR =
|
||||
HTTP_PORT = 3000
|
||||
; Local (DMZ) URL for Gogs workers (such as SSH update) accessing web service.
|
||||
; In most cases you do not need to change the default value.
|
||||
; Alter it only if your SSH server node is not the same as HTTP node.
|
||||
LOCAL_ROOT_URL = http://localhost:%(HTTP_PORT)s/
|
||||
; Disable SSH feature when not available
|
||||
DISABLE_SSH = false
|
||||
; Whether use builtin SSH server or not.
|
||||
@@ -55,7 +61,6 @@ SSH_PORT = 22
|
||||
OFFLINE_MODE = false
|
||||
DISABLE_ROUTER_LOG = false
|
||||
; Generate steps:
|
||||
; $ cd path/to/gogs/custom/https
|
||||
; $ ./gogs cert -ca=true -duration=8760h0m0s -host=myhost.example.com
|
||||
;
|
||||
; Or from a .pfx file exported from the Windows certificate store (do
|
||||
@@ -265,8 +270,8 @@ ADDR =
|
||||
; For "smtp" mode only
|
||||
[log.smtp]
|
||||
LEVEL =
|
||||
; Name displayed in mail title, default is "Diagnostic message from serve"
|
||||
SUBJECT = Diagnostic message from serve
|
||||
; Name displayed in mail title, default is "Diagnostic message from server"
|
||||
SUBJECT = Diagnostic message from server
|
||||
; Mail server
|
||||
HOST =
|
||||
; Mailer user name and password
|
||||
@@ -296,7 +301,8 @@ SCHEDULE = @every 1h
|
||||
; Repository health check
|
||||
[cron.repo_health_check]
|
||||
SCHEDULE = @every 24h
|
||||
; Arguments for command 'git fsck', e.g.: "--unreachable --tags"
|
||||
TIMEOUT = 60s
|
||||
; Arguments for command 'git fsck', e.g. "--unreachable --tags"
|
||||
; see more on http://git-scm.com/docs/git-fsck/1.7.5
|
||||
ARGS =
|
||||
|
||||
@@ -307,7 +313,7 @@ SCHEDULE = @every 24h
|
||||
|
||||
[git]
|
||||
MAX_GIT_DIFF_LINES = 10000
|
||||
; Arguments for command 'git gc', e.g.: "--aggressive --auto"
|
||||
; Arguments for command 'git gc', e.g. "--aggressive --auto"
|
||||
; see more on http://git-scm.com/docs/git-gc/1.7.5
|
||||
GC_ARGS =
|
||||
|
||||
@@ -332,6 +338,10 @@ pl-PL = pl
|
||||
bg-BG = bg
|
||||
it-IT = it
|
||||
|
||||
; Extension mapping to highlight class
|
||||
; e.g. .toml=ini
|
||||
[highlight.mapping]
|
||||
|
||||
[other]
|
||||
SHOW_FOOTER_BRANDING = false
|
||||
; Show version information about gogs and go in the footer
|
||||
|
||||
@@ -1,30 +1,41 @@
|
||||
# This file lists all PUBLIC individuals having contributed content to the translation.
|
||||
# Entries are in alphabetical order.
|
||||
|
||||
Adam Strzelecki <ono AT java DOT pl>
|
||||
Adrian Verde <me AT adrianverde DOT com>
|
||||
Akihiro YAGASAKI <yaggytter AT momiage DOT com>
|
||||
Aleksejs Grocevs <aleksejs AT grocevs DOT pro>
|
||||
Aleksey Tarakin <hukendo AT yandex DOT ru>
|
||||
Alexander Steinhöfer <kontakt AT lx-s DOT de>
|
||||
Alexandre Magno <alexandre DOT mbm AT gmail DOT com>
|
||||
Andrey Nering <andrey AT nering DOT com DOT br>
|
||||
Arthur Aslanyan <arthur DOT e DOT aslanyan AT gmail DOT com>
|
||||
Barış Arda Yılmaz <ardayilmazgamer AT gmail DOT com>
|
||||
Christoph Kisfeld <christoph DOT kisfeld AT gmail DOT com>
|
||||
Cysioland
|
||||
Daniel Speichert <daniel AT speichert DOT pl>
|
||||
David Yzaguirre <dvdyzag AT gmail DOT com>
|
||||
Dmitriy Nogay <me AT catwhocode DOT ga>
|
||||
Ezequiel Gonzalez Rial <gonrial AT gmail DOT com>
|
||||
Gregor Santner <gdev AT live DOT de>
|
||||
Hamid Feizabadi <hamidfzm AT gmail DOT com>
|
||||
Huimin Wang <wanghm2009 AT hotmail DOT co DOT jp>
|
||||
ilko
|
||||
Ilya Makarov
|
||||
Juraj Bubniak <contact AT jbub DOT eu>
|
||||
Lafriks <lafriks AT gmail DOT com>
|
||||
Lauri Ojansivu <x AT xet7 DOT org>
|
||||
Luc Stepniewski <luc AT stepniewski DOT fr>
|
||||
Marc Schiller <marc AT schiller DOT im>
|
||||
Miguel de la Cruz <miguel AT mcrx DOT me>
|
||||
Mikhail Burdin <xdshot9000 AT gmail DOT com>
|
||||
Morten Sørensen <klim8d AT gmail DOT com>
|
||||
Nakao Takamasa <at.mattenn AT gmail DOT com>
|
||||
Natan Albuquerque <natanalbuquerque5 AT gmail DOT com>
|
||||
Odilon Junior <odilon DOT junior93 AT gmail DOT com>
|
||||
Thomas Fanninger <gogs DOT thomas AT fanninger DOT at>
|
||||
Tilmann Bach <tilmann AT outlook DOT com>
|
||||
Toni Villena Jiménez <tonivj5 AT gmail DOT com>
|
||||
Vladimir Vissoultchev <wqweto AT gmail DOT com>
|
||||
YJSoft <yjsoft AT yjsoft DOT pe DOT kr>
|
||||
Łukasz Jan Niemier <lukasz AT niemier DOT pl>
|
||||
|
||||
@@ -2,10 +2,10 @@ app_desc=Безпроблемен собствен Git сървър
|
||||
|
||||
home=Начало
|
||||
dashboard=Табло
|
||||
explore=Преглед
|
||||
explore=Каталог
|
||||
help=Помощ
|
||||
sign_in=Вписване
|
||||
sign_out=Излизане
|
||||
sign_in=Вход
|
||||
sign_out=Изход
|
||||
sign_up=Регистрирайте се
|
||||
register=Регистрация
|
||||
website=Уебсайт
|
||||
@@ -28,6 +28,7 @@ organization=Организация
|
||||
mirror=Огледало
|
||||
new_repo=Ново хранилище
|
||||
new_migrate=Нова миграция
|
||||
new_mirror=Ново огледало
|
||||
new_fork=Ново разклонено хранилище
|
||||
new_org=Нова организация
|
||||
manage_org=Управление на организации
|
||||
@@ -38,8 +39,8 @@ your_profile=Вашият профил
|
||||
your_settings=Вашите настройки
|
||||
|
||||
news_feed=Поток новини
|
||||
pull_requests=Заявки сливане
|
||||
issues=Проблеми
|
||||
pull_requests=Заявки за сливане
|
||||
issues=Задачи
|
||||
|
||||
cancel=Отказ
|
||||
|
||||
@@ -47,7 +48,7 @@ cancel=Отказ
|
||||
search=Търсене...
|
||||
repository=Хранилище
|
||||
user=Потребител
|
||||
issue=Проблем
|
||||
issue=Задача
|
||||
code=Код
|
||||
|
||||
[install]
|
||||
@@ -247,10 +248,11 @@ uid=UID
|
||||
|
||||
public_profile=Публичен профил
|
||||
profile_desc=Вашият адрес на ел. поща е публичен и ще бъде използван за всички свързани с профила Ви уведомления и всички уеб базирани операции, направени чрез сайта.
|
||||
password_username_disabled=Нелокални потребители не могат да променят името си от тук.
|
||||
full_name=Пълно име
|
||||
website=Уебсайт
|
||||
location=Локация
|
||||
update_profile=Обнови профила
|
||||
update_profile=Запази профила
|
||||
update_profile_success=Вашият профил е запазен успешно.
|
||||
change_username=Потребителското име е променено
|
||||
change_username_prompt=Този промяна ще засегне всички връзки сочещи към профила Ви.
|
||||
@@ -260,7 +262,7 @@ cancel=Отказ
|
||||
enable_custom_avatar=Разреши потребителски аватар
|
||||
enable_custom_avatar_helper=Без зареждане от Gravatar
|
||||
choose_new_avatar=Избор на нов аватар
|
||||
update_avatar=Обнови настройките на аватара
|
||||
update_avatar=Запази настройките на аватара
|
||||
uploaded_avatar_not_a_image=Каченият файл не е изображение.
|
||||
no_custom_avatar_available=Невъзможно използване на външен аватар, защото не е активирано.
|
||||
update_avatar_success=Настройките на аватара са запазени успешно.
|
||||
@@ -271,6 +273,7 @@ new_password=Нова парола
|
||||
retype_new_password=Повторно новата парола
|
||||
password_incorrect=Въведената парола не е вярна.
|
||||
change_password_success=Вашата парола е променена успешно. Вече може да влизате, използвайки тази нова парола.
|
||||
password_change_disabled=Нелокални потребители не могат да променят паролата си от тук.
|
||||
|
||||
emails=Адреси на ел. поща
|
||||
manage_emails=Управление на адреси на ел. поща
|
||||
@@ -302,26 +305,26 @@ ssh_key_deletion_desc=При изтриване на този SSH ключ ще
|
||||
ssh_key_deletion_success=SSH ключа беше изтрит успешно!
|
||||
add_on=Добавен на
|
||||
last_used=Последно използван на
|
||||
no_activity=Няма скорошна активност
|
||||
no_activity=Няма скорошна дейност
|
||||
key_state_desc=Този ключ е използван през последните 7 дни
|
||||
token_state_desc=Този токен е използван през последните 7 дни
|
||||
token_state_desc=Този API ключ е използван през последните 7 дни
|
||||
|
||||
manage_social=Управление на свързани профили в социалните мрежи
|
||||
social_desc=Това е списък на свързани профили в социалните мрежи. Премахнете всички, които не разпознавате.
|
||||
unbind=Освобождаване
|
||||
unbind_success=Социалния профил е освободен.
|
||||
|
||||
manage_access_token=Управление на индивидуални токени за достъп
|
||||
generate_new_token=Генериране на нов токен
|
||||
tokens_desc=Генерирани токени, които могат да се използват за достъп до API-то на Gogs.
|
||||
new_token_desc=Всеки токен ще има пълен достъп до Вашия профил.
|
||||
token_name=Име на токена
|
||||
generate_token=Генериране на токен
|
||||
generate_token_succees=Успешно е генериран токен за достъп. Уверете се, че сте го копирали, тъй като няма да можете да го видите отново!
|
||||
manage_access_token=Управление на индивидуални API ключове за достъп
|
||||
generate_new_token=Генериране на нов API ключ
|
||||
tokens_desc=Генерирани API ключове, които могат да се използват за достъп до API на Gogs.
|
||||
new_token_desc=Всеки API ключ ще има пълен достъп до Вашия профил.
|
||||
token_name=Име на API ключ
|
||||
generate_token=Генериране на API ключ
|
||||
generate_token_succees=Успешно е генериран API ключ за достъп. Уверете се, че сте го копирали, тъй като няма да можете да го видите отново!
|
||||
delete_token=Изтрий
|
||||
access_token_deletion=Изтрий индивидуален токен за достъп
|
||||
access_token_deletion_desc=При изтриване на този индивидуален токен за достъп ще се премахнат всички свързани права на приложението. Желаете ли да продължите?
|
||||
delete_token_success=Индивидуалния токен за достъп е изтрит успешно! Не забравяйте да преконфигурирате приложението също.
|
||||
access_token_deletion=Изтрий индивидуален API ключ за достъп
|
||||
access_token_deletion_desc=При изтриване на този индивидуален API ключ за достъп ще се премахнат всички свързани права на приложението. Желаете ли да продължите?
|
||||
delete_token_success=Индивидуалният API ключ за достъп е изтрит успешно! Не забравяйте да преконфигурирате приложението също.
|
||||
|
||||
delete_account=Изтриване на собствения профил
|
||||
delete_prompt=Тази операция ще изтрие Вашия профил завинаги и тя <strong>НЕ МОЖЕ</strong> да бъде отменена в последствие!
|
||||
@@ -352,10 +355,13 @@ auto_init=Инициализиране на това хранилище с из
|
||||
create_repo=Създай хранилище
|
||||
default_branch=Клон по подразбиране
|
||||
mirror_interval=Интервал на отразяване (часове)
|
||||
mirror_address=Адрес на огледало
|
||||
mirror_address_desc=Моля включете потребител и парола в адреса ако са нужни.
|
||||
watchers=Наблюдаващи
|
||||
stargazers=Харесващи
|
||||
forks=Разклонения
|
||||
|
||||
form.reach_limit_of_creation=Притежателят е достигнал настроения лимит от %d брой хранилища.
|
||||
form.name_reserved=Името на хранилището '%s' е запазено.
|
||||
form.name_pattern_not_allowed=Име на хранилището от вида '%s' не е позволено.
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied=Недостатъчни права за импорт
|
||||
migrate.invalid_local_path=Невалиден път - не съществува или не е директория.
|
||||
migrate.failed=Грешка при миграция: %v
|
||||
|
||||
mirror_from=огледало от
|
||||
forked_from=разклонено от
|
||||
fork_from_self=Не можете да разклоните хранилище което си е Ваше!
|
||||
copy_link=Копирай
|
||||
@@ -388,18 +395,18 @@ create_new_repo_command=Създай ново хранилище чрез ком
|
||||
push_exist_repo=Предай съществуващо хранилище през командния ред
|
||||
repo_is_empty=Това хранилище е празно. Моля проверете по-късно пак!
|
||||
|
||||
code=Code
|
||||
code=Код
|
||||
branch=Клон
|
||||
tree=ИН на ревизия
|
||||
filter_branch_and_tag=Филтър по маркер или клон
|
||||
branches=Клонове
|
||||
tags=Маркери
|
||||
issues=Проблеми
|
||||
pulls=Заявки сливане
|
||||
issues=Задачи
|
||||
pulls=Заявки за сливане
|
||||
labels=Етикети
|
||||
milestones=Етапи
|
||||
commits=Ревизии
|
||||
releases=Издания
|
||||
releases=Версии
|
||||
file_raw=Директен файл
|
||||
file_history=История
|
||||
file_view_raw=Виж директен файл
|
||||
@@ -414,7 +421,7 @@ commits.date=Дата
|
||||
commits.older=По-стари
|
||||
commits.newer=По-нови
|
||||
|
||||
issues.new=Нов проблем
|
||||
issues.new=Нова задача
|
||||
issues.new.labels=Етикети
|
||||
issues.new.no_label=Няма етикет
|
||||
issues.new.clear_labels=Изчисти етикети
|
||||
@@ -426,7 +433,7 @@ issues.new.closed_milestone=Затворени етапи
|
||||
issues.new.assignee=Изпълнител
|
||||
issues.new.clear_assignee=Изчисти изпълнител
|
||||
issues.new.no_assignee=Няма изпълнител
|
||||
issues.create=Докладвай проблем
|
||||
issues.create=Създай задача
|
||||
issues.new_label=Нов етикет
|
||||
issues.new_label_placeholder=Име на етикета...
|
||||
issues.create_label=Създай етикет
|
||||
@@ -439,7 +446,7 @@ issues.filter_milestone_no_select=Липсва избран етап
|
||||
issues.filter_assignee=Изпълнител
|
||||
issues.filter_assginee_no_select=Няма избран изпълнител
|
||||
issues.filter_type=Тип
|
||||
issues.filter_type.all_issues=Всички проблеми
|
||||
issues.filter_type.all_issues=Всички задачи
|
||||
issues.filter_type.assigned_to_you=Възложени на Вас
|
||||
issues.filter_type.created_by_you=Създадени от Вас
|
||||
issues.filter_type.mentioning_you=Споменават лично
|
||||
@@ -466,7 +473,7 @@ issues.reopen_comment_issue=Kоментирай и oтвори отново
|
||||
issues.create_comment=Коментирай
|
||||
issues.closed_at=`затвори <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.reopened_at=`повторно отвори <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commit_ref_at=`посочи този проблем от ревизия <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commit_ref_at=`посочи тази задача от ревизия <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.poster=Участник
|
||||
issues.admin=Администратор
|
||||
issues.owner=Притежател
|
||||
@@ -478,12 +485,12 @@ issues.save=Запис
|
||||
issues.label_title=Име на етикета
|
||||
issues.label_color=Цвят на етикет
|
||||
issues.label_count=%d етикети
|
||||
issues.label_open_issues=%d отворени проблема
|
||||
issues.label_open_issues=%d отворени задачи
|
||||
issues.label_edit=Редакция
|
||||
issues.label_delete=Изтрий
|
||||
issues.label_modify=Промяна на етикет
|
||||
issues.label_deletion=Изтрий етикет
|
||||
issues.label_deletion_desc=При изтриване на този етикет ще се премахне информацията за него във всички свързани проблеми. Желаете ли да продължите?
|
||||
issues.label_deletion_desc=При изтриване на този етикет ще се премахне информацията за него във всички свързани задачи. Желаете ли да продължите?
|
||||
issues.label_deletion_success=Етикетът е изтрит успешно!
|
||||
|
||||
pulls.new=Нова заявка за сливане
|
||||
@@ -506,9 +513,9 @@ pulls.merged=Обединени
|
||||
pulls.has_merged=Тази заявка за сливане е обединена успешно!
|
||||
pulls.data_broken=Данните от тази заявка за сливане са невалидни поради изтрита информация за някое разклонение.
|
||||
pulls.is_checking=Проверката за конфликт все още е в ход. Моля обновете страницата след малко.
|
||||
pulls.can_auto_merge_desc=Можете да извършвате авто-обединяване на тази заявка за сливане.
|
||||
pulls.cannot_auto_merge_desc=Не можете да извършите авто-обединяване, защото съществуват конфликти между ревизиите.
|
||||
pulls.cannot_auto_merge_helper=Моля, използвайте инструменти на командния ред за да отстраните проблема.
|
||||
pulls.can_auto_merge_desc=Може да се извърши обединяване на тази заявка за сливане.
|
||||
pulls.cannot_auto_merge_desc=Не може да се извърши обединяване, защото съществуват конфликти между ревизиите.
|
||||
pulls.cannot_auto_merge_helper=Моля, използвайте инструменти на командния ред за да разрешите конфликтите.
|
||||
pulls.merge_pull_request=Обедини заявка за сливане
|
||||
pulls.open_unmerged_pull_exists=`Невъзможно повторно отваряне, защото вече съществува заявка за сливане (#%d) от същото хранилище със същата информация за обединяване, която чака да бъде извършена`
|
||||
|
||||
@@ -519,7 +526,7 @@ milestones.closed=Затворен %s
|
||||
milestones.no_due_date=Няма краен срок
|
||||
milestones.open=Отвори
|
||||
milestones.close=Затвори
|
||||
milestones.new_subheader=Създайте етапи за да организирате проблемите.
|
||||
milestones.new_subheader=Създайте етапи за да организирате задачите.
|
||||
milestones.create=Създай етап
|
||||
milestones.title=Заглавие
|
||||
milestones.desc=Описание
|
||||
@@ -533,7 +540,7 @@ milestones.cancel=Отказ
|
||||
milestones.modify=Промяна на етап
|
||||
milestones.edit_success=Промените в етап '%s' са запазени успешно!
|
||||
milestones.deletion=Изтрий етап
|
||||
milestones.deletion_desc=При изтриване на етап ще се премахне информацията за него от всички свързани проблеми. Желаете ли да продължите?
|
||||
milestones.deletion_desc=При изтриване на етап ще се премахне информацията за него от всички свързани задачи. Желаете ли да продължите?
|
||||
milestones.deletion_success=Етапът е изтрит успешно!
|
||||
|
||||
wiki=Уики
|
||||
@@ -559,15 +566,18 @@ settings.hooks=Уеб-куки
|
||||
settings.githooks=Git куки
|
||||
settings.basic_settings=Основни настройки
|
||||
settings.site=Официален сайт
|
||||
settings.update_settings=Обнови настройките
|
||||
settings.update_settings=Запази настройките
|
||||
settings.change_reponame_prompt=Тази промяна ще засегне връзките, които се отнасят до това хранилището.
|
||||
settings.advanced_settings=Advanced Settings
|
||||
settings.wiki_desc=Enable wiki to allow people write documents
|
||||
settings.issues_desc=Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Use external issue tracker
|
||||
settings.tracker_url_format=External Issue Tracker URL Format
|
||||
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc=Enable pull requests to accept public contributions
|
||||
settings.advanced_settings=Разширени настройки
|
||||
settings.wiki_desc=Включва уики за да може потребителите да създават документи
|
||||
settings.use_external_wiki=Използвай външно уики
|
||||
settings.external_wiki_url=URL адрес на външно уики
|
||||
settings.external_wiki_url_desc=Посетителите ще бъдат пренасочени към този URL адрес от връзката за раздел уики.
|
||||
settings.issues_desc=Включва вградена система за проследяване на задачи
|
||||
settings.use_external_issue_tracker=Използвай външна система за проследяване на задачи
|
||||
settings.tracker_url_format=Формат на URL адрес на външна система за проследяване на задачи
|
||||
settings.tracker_url_format_desc=Можете да използвате текстови маркери <code>{user} {repo} {index}</code> за потребителско име, име на хранилище и индекс на задача съответно.
|
||||
settings.pulls_desc=Включва заявки за сливане за да може да се приемат външни доработки
|
||||
settings.danger_zone=Опасна зона
|
||||
settings.transfer=Прехвърли притежание
|
||||
settings.transfer_desc=Прехвърля това хранилище на друг потребител или към организация, в която имате права на администратор.
|
||||
@@ -578,11 +588,11 @@ settings.transfer_notices_1=- Вие ще загубите достъп, ако
|
||||
settings.transfer_notices_2=- Вие ще запазите достъпа си, ако новият притежател е организация и ако вие сте един от притежателите ѝ.
|
||||
settings.transfer_form_title=Моля въведете следната информация за да потвърдите операцията:
|
||||
settings.delete_notices_1=- Тази операция <strong>НЕ МОЖЕ</strong> да бъде отменена в последствие.
|
||||
settings.delete_notices_2=- Тази операция ще изтрие всичко от това хранилище, включително Git данни, проблеми, коментари и достъпа на сътрудници.
|
||||
settings.delete_notices_2=- Тази операция ще изтрие всичко от това хранилище, включително Git данни, задачи, коментари и достъпа на сътрудници.
|
||||
settings.delete_notices_fork_1=- Ако това хранилище е публично, всички негови разклонения ще останат независими след изтриването му.
|
||||
settings.delete_notices_fork_2=- Ако това хранилище е частно, всички негови разклонения ще бъдат премахнати по време на изтриването.
|
||||
settings.delete_notices_fork_3=- Ако желаете да запазите всички разклонения след изтриването му, първо направете хранилището публично.
|
||||
settings.deletion_success=Repository has been deleted successfully!
|
||||
settings.deletion_success=Хранилището е изтрито успешно!
|
||||
settings.update_settings_success=Настройките на хранилището са запазени успешно.
|
||||
settings.transfer_owner=Нов притежател
|
||||
settings.make_transfer=Прехвърли
|
||||
@@ -598,9 +608,9 @@ settings.hooks_desc=Уеб-куките много приличат на оби
|
||||
settings.webhook_deletion=Изтрий уеб-кука
|
||||
settings.webhook_deletion_desc=При изтриване на тази уеб-кука ще се премахне информацията за нея и цялата хронология на нейното изпращане. Желаете ли да продължите?
|
||||
settings.webhook_deletion_success=Уеб-куката е изтрита успешно!
|
||||
settings.webhook.test_delivery=Test Delivery
|
||||
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.test_delivery=Тестово изпращане
|
||||
settings.webhook.test_delivery_desc=Симулира тестово изпращане за тест на настройките на уеб-куката
|
||||
settings.webhook.test_delivery_success=Тестовата уеб-кука е добавена в опашката за изпращане. Може да отнеме няколко секунди преди да се появи в историята с доставени.
|
||||
settings.webhook.request=Заявка
|
||||
settings.webhook.response=Отговор
|
||||
settings.webhook.headers=Заглавки
|
||||
@@ -610,7 +620,7 @@ settings.githooks_desc=Git куките се изпълняват от Git. Ви
|
||||
settings.githook_edit_desc=Ако куката е неактивна, ще бъде представено примерно съдържание. Ако оставите съдържанието празно, то тази кука ще бъде изключена.
|
||||
settings.githook_name=Име на куката
|
||||
settings.githook_content=Съдържание на куката
|
||||
settings.update_githook=Обнови куката
|
||||
settings.update_githook=Запази куката
|
||||
settings.add_webhook_desc=Gogs ще изпрати <code>POST</code> заявка към указания URL адрес заедно с информация за събитието, което е настъпило. Също можете да укажете в какъв формат желаете да получите данните при задействане на куката (JSON, x-www-form-urlencoded, XML) и др. Допълнително описание можете да намерите в нашето <a target="_blank" href="%s">Ръководство за уеб-куки</a>.
|
||||
settings.payload_url=URL адрес на изпращане
|
||||
settings.content_type=Тип на съдържанието
|
||||
@@ -629,13 +639,13 @@ settings.event_push_desc=Git предаване към хранилището
|
||||
settings.active=Активна
|
||||
settings.active_helper=Подробности относно събитието, което е задействало куката, също ще бъдат изпратени.
|
||||
settings.add_hook_success=Новата уеб-кука е добавена успешно.
|
||||
settings.update_webhook=Обнови уеб-куката
|
||||
settings.update_webhook=Запази уеб-куката
|
||||
settings.update_hook_success=Уеб-куката е запазена успешно.
|
||||
settings.delete_webhook=Изтрий уеб-куката
|
||||
settings.recent_deliveries=Последни изпращания
|
||||
settings.hook_type=Тип на куката
|
||||
settings.add_slack_hook_desc=Добавяне на интеграция със <a href="%s">Slack</a> във Вашето хранилище.
|
||||
settings.slack_token=Токен
|
||||
settings.slack_token=API ключ
|
||||
settings.slack_domain=Домейн
|
||||
settings.slack_channel=Канал
|
||||
settings.deploy_keys=Ключове за внедряване
|
||||
@@ -660,15 +670,15 @@ diff.stats_desc=променени са <strong>%d файла</strong>, в ко
|
||||
diff.bin=BIN
|
||||
diff.view_file=Целия файл
|
||||
|
||||
release.releases=Издания
|
||||
release.new_release=Ново издание
|
||||
release.releases=Версии
|
||||
release.new_release=Нова версия
|
||||
release.draft=Чернови
|
||||
release.prerelease=Предварителни
|
||||
release.stable=Стабилни
|
||||
release.edit=редактиране
|
||||
release.ahead=<strong>%d</strong> ревизии на %s след това издание
|
||||
release.ahead=<strong>%d</strong> ревизии на %s след тази версия
|
||||
release.source_code=Изходен код
|
||||
release.new_subheader=Публикувайте издания на всяка нова итерация.
|
||||
release.new_subheader=Публикувайте версия на всяка нова итерация.
|
||||
release.edit_subheader=Подробният журнал на промените ще помогне на потребителите да разберат какви подобрения са направени.
|
||||
release.tag_name=Име на маркера
|
||||
release.target=Цел
|
||||
@@ -678,17 +688,17 @@ release.content=Съдържание
|
||||
release.write=Редактор
|
||||
release.preview=Преглед
|
||||
release.loading=Зареждане...
|
||||
release.prerelease_desc=Това е предварително издание
|
||||
release.prerelease_helper=Ние ще отбележим, че това издание не е завършено за употреба.
|
||||
release.prerelease_desc=Това е предварителна версия
|
||||
release.prerelease_helper=Ние ще отбележим, че тази версия не е готова за продукционна употреба.
|
||||
release.cancel=Отказ
|
||||
release.publish=Публикувай издание
|
||||
release.publish=Публикувай версия
|
||||
release.save_draft=Запис на чернова
|
||||
release.edit_release=Редактирай издание
|
||||
release.delete_release=Изтриване на това издание
|
||||
release.deletion=Изтрий изданието
|
||||
release.deletion_desc=При изтриване на това издание ще се премахне съответния Git маркер. Желаете ли да продължите?
|
||||
release.deletion_success=Изданието беше изтрито успешно!
|
||||
release.tag_name_already_exist=Издание с това име на маркер вече съществува.
|
||||
release.edit_release=Редактирай версия
|
||||
release.delete_release=Изтриване на тази версия
|
||||
release.deletion=Изтрий версията
|
||||
release.deletion_desc=При изтриване на тази версия ще се премахне и съответния Git маркер. Желаете ли да продължите?
|
||||
release.deletion_success=Версията беше изтрита успешно!
|
||||
release.tag_name_already_exist=Версия с това име на маркер вече съществува.
|
||||
release.downloads=Изтегляния
|
||||
|
||||
[org]
|
||||
@@ -718,7 +728,7 @@ settings.options=Опции
|
||||
settings.full_name=Пълно име
|
||||
settings.website=Уебсайт
|
||||
settings.location=Локация
|
||||
settings.update_settings=Обнови настройките
|
||||
settings.update_settings=Запази настройките
|
||||
settings.update_setting_success=Настройките на организацията са запазени успешно.
|
||||
settings.change_orgname_prompt=Този промяна ще засегне всички връзки сочещи към организацията.
|
||||
settings.update_avatar_success=Настройките на аватара на организацията са запазени успешно.
|
||||
@@ -755,7 +765,7 @@ teams.no_desc=Този екип няма описание
|
||||
teams.settings=Настройки
|
||||
teams.owners_permission_desc=Притежателите имат пълен достъп до <strong>всички хранилища</strong> и имат <strong>права на администратори</strong> на организацията.
|
||||
teams.members=Участници в екипа
|
||||
teams.update_settings=Обнови настройките
|
||||
teams.update_settings=Запази настройките
|
||||
teams.delete_team=Изтриване на този екип
|
||||
teams.add_team_member=Добави участник в екипа
|
||||
teams.delete_team_title=Изтрий екипа
|
||||
@@ -786,7 +796,7 @@ total=Общо: %d
|
||||
dashboard.statistic=Статистика
|
||||
dashboard.operations=Операции
|
||||
dashboard.system_status=Наблюдение на системния статус
|
||||
dashboard.statistic_info=Gogs базата данни има <b>%d</b> потребители, <b>%d</b> организации, <b>%d</b> публични ключове, <b>%d</b> хранилища, <b>%d</b> наблюдавания, <b>%d</b> харесвания, <b>%d</b> действия, <b>%d</b> достъпи, <b>%d</b> проблеми, <b>%d</b> коментари, <b>%d</b> социални регистрации, <b>%d</b> последователи, <b>%d</b> огледала, <b>%d</b> издания, <b>%d</b> източници за вписване, <b>%d</b> уеб-куки, <b>%d</b> етапи, <b>%d</b> етикети, <b>%d</b> задачи на куки, <b>%d</b> екипи, <b>%d</b> задачи при актуализация, <b>%d</b> прикачени файлове.
|
||||
dashboard.statistic_info=Gogs базата данни има <b>%d</b> потребители, <b>%d</b> организации, <b>%d</b> публични ключове, <b>%d</b> хранилища, <b>%d</b> наблюдавания, <b>%d</b> харесвания, <b>%d</b> действия, <b>%d</b> достъпи, <b>%d</b> задачи, <b>%d</b> коментари, <b>%d</b> социални регистрации, <b>%d</b> последователи, <b>%d</b> огледала, <b>%d</b> версии, <b>%d</b> начини на удостоверяване, <b>%d</b> уеб-куки, <b>%d</b> етапи, <b>%d</b> етикети, <b>%d</b> задачи на куки, <b>%d</b> екипи, <b>%d</b> задачи при актуализация, <b>%d</b> прикачени файлове.
|
||||
dashboard.operation_name=Име на операцията
|
||||
dashboard.operation_switch=Превключи
|
||||
dashboard.operation_run=Изпълни
|
||||
@@ -845,17 +855,19 @@ users.created=Създаване
|
||||
users.send_register_notify=Прати уведомление на потребителя при регистрация
|
||||
users.new_success=Новият профил '%s' е добавен успешно.
|
||||
users.edit=Редакция
|
||||
users.auth_source=Източник за удостоверяване
|
||||
users.auth_source=Начин на удостоверяване
|
||||
users.local=Локално
|
||||
users.auth_login_name=Потребителско име за удостоверяване
|
||||
users.auth_login_name=Потребителско име за вход
|
||||
users.password_helper=Оставете празна ако не се променя.
|
||||
users.update_profile_success=Профилът е запазен успешно.
|
||||
users.edit_account=Редактирай профил
|
||||
users.max_repo_creation=Макс. брой хранилища
|
||||
users.max_repo_creation_desc=(Задайте -1 за да се използва глобалния лимит)
|
||||
users.is_activated=Този профил е активиран
|
||||
users.is_admin=Този профил има административни права
|
||||
users.allow_git_hook=Този профил има разрешение да създава Git куки
|
||||
users.allow_import_local=Този профил има права за импорт на локални хранилища
|
||||
users.update_profile=Обнови профила
|
||||
users.update_profile=Запази профила
|
||||
users.delete_account=Изтрий този профил
|
||||
users.still_own_repo=Този профил притежава поне едно хранилище. Първо трябва да изтриете хранилището или да го прехвърлите на друг потребител.
|
||||
users.still_has_org=Този профил участва в поне една организация. Първо трябва да напуснете или изтриете тези организации.
|
||||
@@ -872,10 +884,10 @@ repos.name=Име
|
||||
repos.private=Частно
|
||||
repos.watches=Наблюдавания
|
||||
repos.stars=Харесвания
|
||||
repos.issues=Проблеми
|
||||
repos.issues=Задачи
|
||||
|
||||
auths.auth_manage_panel=Управление на удостоверявания
|
||||
auths.new=Добави нов източник за удостоверяване
|
||||
auths.new=Добави нов начин на удостоверяване
|
||||
auths.name=Име
|
||||
auths.type=Тип
|
||||
auths.enabled=Активно
|
||||
@@ -912,7 +924,7 @@ auths.edit=Редактирай настройки за удостоверява
|
||||
auths.activated=Това удостоверяване е активно
|
||||
auths.new_success=Новото удостоверяване '%s' е добавено успешно.
|
||||
auths.update_success=Настройките за удостоверяване са запазени успешно.
|
||||
auths.update=Обнови настройки за удостоверяване
|
||||
auths.update=Запази настройки за удостоверяване
|
||||
auths.delete=Изтриване на това удостоверяване
|
||||
auths.delete_auth_title=Изтрий удостоверяването
|
||||
auths.delete_auth_desc=Това удостоверяване ще бъде изтрито. Желаете ли да продължите?
|
||||
@@ -995,30 +1007,30 @@ monitor.start=Начален час
|
||||
monitor.execute_time=Време за изпълнение
|
||||
|
||||
notices.system_notice_list=Системни известия
|
||||
notices.view_detail_header=View Notice Detail
|
||||
notices.actions=Actions
|
||||
notices.select_all=Select All
|
||||
notices.deselect_all=Deselect All
|
||||
notices.inverse_selection=Inverse Selection
|
||||
notices.delete_selected=Delete Selected
|
||||
notices.delete_all=Delete All Notices
|
||||
notices.view_detail_header=Преглед на детайли на съобщение
|
||||
notices.actions=Действия
|
||||
notices.select_all=Избери всички
|
||||
notices.deselect_all=Без избрани
|
||||
notices.inverse_selection=Обърни избора
|
||||
notices.delete_selected=Изтрий избраните
|
||||
notices.delete_all=Изтрий всички съобщения
|
||||
notices.type=Тип
|
||||
notices.type_1=Хранилище
|
||||
notices.desc=Описание
|
||||
notices.op=Oп.
|
||||
notices.delete_success=System notices have been deleted successfully.
|
||||
notices.delete_success=Системните съобщения са изтрити успешно.
|
||||
|
||||
[action]
|
||||
create_repo=създаде хранилище <a href="%s"> %s</a>
|
||||
rename_repo=преименува хранилище от <code>%[1]s</code> на <a href="%[2]s">%[3]s</a>
|
||||
commit_repo=предаде към <a href="%[1]s/src/%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a>
|
||||
create_issue=`отвори проблем <a href="%s/issues/%s">%s#%[2]s"</a>`
|
||||
create_issue=`отвори задача <a href="%s/issues/%s">%s#%[2]s"</a>`
|
||||
create_pull_request=`създаде заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
comment_issue=`коментира проблем <a href="%s/issues/%s">%s#%[2]s"</a>`
|
||||
comment_issue=`коментира задача <a href="%s/issues/%s">%s#%[2]s"</a>`
|
||||
merge_pull_request=`обедини заявка за сливане <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo=прехвърли хранилище <code>%s</code> към <a href="%s">%s</a>
|
||||
push_tag=предаде маркер <a href="%s/src/%s">%[2]s</a> към <a href="%[1]s">[3]s</a>
|
||||
compare_2_commits=Сравнение между тези 2 ревизии
|
||||
compare_commits=Сравнение между тези %d ревизии
|
||||
|
||||
[tool]
|
||||
ago=преди
|
||||
|
||||
@@ -28,6 +28,7 @@ organization=Organisation
|
||||
mirror=Spiegel
|
||||
new_repo=Neues Repository
|
||||
new_migrate=Neue Migration
|
||||
new_mirror=Neuer Spiegel
|
||||
new_fork=Neues abgespaltetes Repository
|
||||
new_org=Neue Organisation
|
||||
manage_org=Organisationen verwalten
|
||||
@@ -247,6 +248,7 @@ uid=Uid
|
||||
|
||||
public_profile=Öffentliches Profil
|
||||
profile_desc=Deine E-Mail-Adresse ist öffentlich einsehbar und wird für accountspezifische Benachrichtigungen verwendet, sowie für alle web-basierten Funktionen, die über die Seite gemacht werden.
|
||||
password_username_disabled=Nicht-lokalen Benutzern ist es nicht erlaubt, ihren Usernamen zu ändern.
|
||||
full_name=Vollständiger Name
|
||||
website=Webseite
|
||||
location=Standort
|
||||
@@ -271,6 +273,7 @@ new_password=Neues Passwort
|
||||
retype_new_password=Neues Passwort erneut eingeben
|
||||
password_incorrect=Aktuelles Passwort ist nicht korrekt.
|
||||
change_password_success=Passwort geändert. Du kannst dich jetzt mit deinem neuen Passwort anmelden.
|
||||
password_change_disabled=Nicht-lokalen Benutzern ist es nicht erlaubt, ihr Passwort zu ändern.
|
||||
|
||||
emails=E-Mail-Adressen
|
||||
manage_emails=E-Mail-Adressen verwalten
|
||||
@@ -352,10 +355,13 @@ auto_init=Repository mit ausgewählten Dateien und Vorlagen initialisieren
|
||||
create_repo=Repository erstellen
|
||||
default_branch=Standard-Branch
|
||||
mirror_interval=Spiegel-Intervall (in Stunden)
|
||||
mirror_address=Spiegeladresse
|
||||
mirror_address_desc=Bitte notwendige Benutzerangaben in die Adresse aufnehmen.
|
||||
watchers=Beobachter
|
||||
stargazers=Sterngucker
|
||||
forks=Forks
|
||||
|
||||
form.reach_limit_of_creation=Der Besitzer hat die maximale Anzahl vo %d erstellbaren Repositorys erreicht.
|
||||
form.name_reserved=Repository-Name '%s' ist bereits vergeben.
|
||||
form.name_pattern_not_allowed=Repository-Namesmuster '%s' ist nicht zulässig.
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied=Ihnen fehlen die Rechte zum Importieren lokaler Reposi
|
||||
migrate.invalid_local_path=Lokaler Pfad ist ungültig, er existiert nicht oder ist kein Ordner.
|
||||
migrate.failed=Fehler bei Migration: %v
|
||||
|
||||
mirror_from=spiegeln von
|
||||
forked_from=Geforkt von
|
||||
fork_from_self=Sie können keine Repository forken, welche ihnen gehört!
|
||||
copy_link=Kopieren
|
||||
@@ -506,9 +513,9 @@ pulls.merged=Zusammengeführt
|
||||
pulls.has_merged=Dieser Pull-Request wurde erfolgreich zusammengeführt!
|
||||
pulls.data_broken=Die Daten dieser Pull-Anforderung sind defekt aufgrund des Löschens von Fork-Informationen.
|
||||
pulls.is_checking=Die Konfliktprüfung ist in Arbeit. Bitte aktualisiere die Seite in wenigen Momenten.
|
||||
pulls.can_auto_merge_desc=Du kannst eine Auto-Merge Operation auf diese Pull-Anforderung durchführen.
|
||||
pulls.cannot_auto_merge_desc=Es kann keine Auto-Merge Operation durchgeführt werden, da es Konflikte zwischen den Commits gibt.
|
||||
pulls.cannot_auto_merge_helper=Bitte benutze ein Kommandozeilentool, um den Konflikt zu lösen.
|
||||
pulls.can_auto_merge_desc=Diese Pull-Anforderung kann automatisch zusammengeführt werden.
|
||||
pulls.cannot_auto_merge_desc=Diese Pull-Anforderung kann nicht automatisch zusammengeführt werden, da es Konflikte gibt.
|
||||
pulls.cannot_auto_merge_helper=Bitte manuell zusammenführen um die Konflikte zu lösen.
|
||||
pulls.merge_pull_request=Pull-Request zusammenführen
|
||||
pulls.open_unmerged_pull_exists=`Du kannst die Pull-Anforderung nicht wiedereröffnen, da bereits eine offene Pull-Anforderung (#%d) aus dem selben Repository mit den gleichen Merge-Informationen existiert und auf das Merging wartet.`
|
||||
|
||||
@@ -561,13 +568,16 @@ settings.basic_settings=Grundeinstellungen
|
||||
settings.site=Offizielle Webseite
|
||||
settings.update_settings=Einstellungen speichern
|
||||
settings.change_reponame_prompt=Diese Änderung wirkt sich darauf aus, wie sich Links auf Repositories beziehen.
|
||||
settings.advanced_settings=Advanced Settings
|
||||
settings.wiki_desc=Enable wiki to allow people write documents
|
||||
settings.issues_desc=Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Use external issue tracker
|
||||
settings.tracker_url_format=External Issue Tracker URL Format
|
||||
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc=Enable pull requests to accept public contributions
|
||||
settings.advanced_settings=Erweiterte Einstellungen
|
||||
settings.wiki_desc=Wiki aktivieren um Leuten das Schreiben von Dokumenten zu ermöglichen
|
||||
settings.use_external_wiki=Benutze externes Wiki
|
||||
settings.external_wiki_url=Externe Wiki URL
|
||||
settings.external_wiki_url_desc=Besucher werden auf die URL umgeleitet, wenn sie auf den Tab klicken.
|
||||
settings.issues_desc=Benutze eingebauten leichtgewichtigen Issue-Tracker
|
||||
settings.use_external_issue_tracker=Benutze externen Issue-Tracker
|
||||
settings.tracker_url_format=URL-Format für externen Issu-Tracker
|
||||
settings.tracker_url_format_desc=Du kannst einen Platzhalter <code>{user} {repo} {index}</code> für den Benutzernamen, den Repositorynamen und den Issue-Index benutzen.
|
||||
settings.pulls_desc=Aktiviere Pull-Anforderungen zum Akzeptieren von öffentlichen Beiträgen
|
||||
settings.danger_zone=Gefahrenzone
|
||||
settings.transfer=Besitz übertragen
|
||||
settings.transfer_desc=Übertrage diese Repository auf einen anderen Benutzer oder eine Organisation in der du Admin-Rechte hast.
|
||||
@@ -582,7 +592,7 @@ settings.delete_notices_2=- Die Operation wird alles, was mit dieser Git-Reposit
|
||||
settings.delete_notices_fork_1=- Wenn dies eine öffentliche Repository ist, werden nach der Löschung alle Forks unabhängig.
|
||||
settings.delete_notices_fork_2=- Wenn dies eine private Repository ist, dann werden gleichzeitig alle Forks entfernt.
|
||||
settings.delete_notices_fork_3=Wenn alle Forks erhalten bleiben sollen, dann muss zuerst die Sichtbarkeit der Repository auf öffentlich gesetzt werden.
|
||||
settings.deletion_success=Repository has been deleted successfully!
|
||||
settings.deletion_success=Repository wurde erfolgreich gelöscht!
|
||||
settings.update_settings_success=Repository-Optionen aktualisiert.
|
||||
settings.transfer_owner=Neuer Besitzer
|
||||
settings.make_transfer=übertragen
|
||||
@@ -598,9 +608,9 @@ settings.hooks_desc=Webhooks erlauben es dir, externe Dienste zu informieren, we
|
||||
settings.webhook_deletion=Webhook entfernen
|
||||
settings.webhook_deletion_desc=Das Löschen dieses Webhooks wird alle zugehörigen Informationen und den Übertragungsverlauf entfernen. Wirklich fortfahren?
|
||||
settings.webhook_deletion_success=Webhook wurde erfolgreich entfernt!
|
||||
settings.webhook.test_delivery=Test Delivery
|
||||
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.test_delivery=Auslieferungstest
|
||||
settings.webhook.test_delivery_desc=Sende eine imitierte Push-Ereignis-Auslieferung um die Webhook-Einstellungen zu testen
|
||||
settings.webhook.test_delivery_success=Test-Webhook wurde zur Auslieferungswarteschlange hinzugefügt. Es kann einige Sekunden dauern, bevor es in der Auslieferungshistorie erscheint.
|
||||
settings.webhook.request=Anfrage
|
||||
settings.webhook.response=Rückmeldung
|
||||
settings.webhook.headers=Kopfzeilen
|
||||
@@ -640,7 +650,7 @@ settings.slack_domain=Domain
|
||||
settings.slack_channel=Kanal
|
||||
settings.deploy_keys=Deploy-Keys
|
||||
settings.add_deploy_key=Deploy-Key hinzufügen
|
||||
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys.
|
||||
settings.deploy_key_desc=Auslieferungs-Schlüssel hat nur lesenden Zugriff. Er ist nicht identisch mit dem persönlichen SSH-Schlüssel des Accounts.
|
||||
settings.no_deploy_keys=Du hast noch keine Deploy-Schlüssel hinzugefügt.
|
||||
settings.title=Titel
|
||||
settings.deploy_key_content=Inhalt
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name=Authentifizierung-Loginnname
|
||||
users.password_helper=Leer lassen um es unverändert zu lassen.
|
||||
users.update_profile_success=Kontoprofil wurde erfolgreich aktualisiert.
|
||||
users.edit_account=Konto bearbeiten
|
||||
users.max_repo_creation=Limit zum Erstellen von Repositorys
|
||||
users.max_repo_creation_desc=(auf -1 setzen, um das globale Standardlimit zu verwenden)
|
||||
users.is_activated=Dieses Konto ist aktiviert
|
||||
users.is_admin=Dieses Konto hat Administratorrechte
|
||||
users.allow_git_hook=Dieses Konto ist berechtigt, Git-Hooks zu erstellen
|
||||
@@ -995,18 +1007,18 @@ monitor.start=Startzeit
|
||||
monitor.execute_time=Ausführungszeit
|
||||
|
||||
notices.system_notice_list=System-Mitteilungen
|
||||
notices.view_detail_header=View Notice Detail
|
||||
notices.actions=Actions
|
||||
notices.select_all=Select All
|
||||
notices.deselect_all=Deselect All
|
||||
notices.inverse_selection=Inverse Selection
|
||||
notices.delete_selected=Delete Selected
|
||||
notices.delete_all=Delete All Notices
|
||||
notices.view_detail_header=Mitteilungsdetails ansehen
|
||||
notices.actions=Aktionen
|
||||
notices.select_all=Alles auswählen
|
||||
notices.deselect_all=Alles abwählen
|
||||
notices.inverse_selection=Auswahl umkehren
|
||||
notices.delete_selected=Augewählte löschen
|
||||
notices.delete_all=Alle Mitteilungen löschen
|
||||
notices.type=Typ
|
||||
notices.type_1=Repository
|
||||
notices.desc=Beschreibung
|
||||
notices.op=Op.
|
||||
notices.delete_success=System notices have been deleted successfully.
|
||||
notices.delete_success=Systemmitteilungen wurden erfolgreich gelöscht.
|
||||
|
||||
[action]
|
||||
create_repo=hat Repository <a href="%s">%s</a> erstellt
|
||||
@@ -1018,7 +1030,7 @@ comment_issue=`hat Issue <a href="%s/issues/%s">%s#%[2]s</a> kommentiert`
|
||||
merge_pull_request=`Pull-Request <a href="%s/pulls/%s">%s#%[2]s</a> zuammengeführt`
|
||||
transfer_repo=hat Repository <code>%s</code> transferiert an <a href="%s">%s</a>
|
||||
push_tag=hat nach <a href="%s/src/%s">%[2]s</a> in <a href="%[1]s">%[3]s</a> gepusht
|
||||
compare_2_commits=Zeige Vergleich dieser 2 Commits
|
||||
compare_commits=Zeige Vergleich für diese %d Commits
|
||||
|
||||
[tool]
|
||||
ago=vor
|
||||
|
||||
@@ -28,6 +28,7 @@ organization = Organization
|
||||
mirror = Mirror
|
||||
new_repo = New Repository
|
||||
new_migrate = New Migration
|
||||
new_mirror = New Mirror
|
||||
new_fork = New Fork Repository
|
||||
new_org = New Organization
|
||||
manage_org = Manage Organizations
|
||||
@@ -247,6 +248,7 @@ uid = Uid
|
||||
|
||||
public_profile = Public Profile
|
||||
profile_desc = Your email address is public and will be used for any account related notifications, and any web based operations made via the site.
|
||||
password_username_disabled = Non-local type users are not allowed to change their username.
|
||||
full_name = Full Name
|
||||
website = Website
|
||||
location = Location
|
||||
@@ -271,6 +273,7 @@ new_password = New Password
|
||||
retype_new_password = Retype New Password
|
||||
password_incorrect = Current password is not correct.
|
||||
change_password_success = Your password was successfully changed. You can now sign using this new password.
|
||||
password_change_disabled = Non-local type users are not allowed to change their password.
|
||||
|
||||
emails = Email Addresses
|
||||
manage_emails = Manage email addresses
|
||||
@@ -352,10 +355,13 @@ auto_init = Initialize this repository with selected files and template
|
||||
create_repo = Create Repository
|
||||
default_branch = Default Branch
|
||||
mirror_interval = Mirror Interval (hour)
|
||||
mirror_address = Mirror Address
|
||||
mirror_address_desc = Please include necessary user credentials in the address.
|
||||
watchers = Watchers
|
||||
stargazers = Stargazers
|
||||
forks = Forks
|
||||
|
||||
form.reach_limit_of_creation = The owner has reached maximum creation limit of %d repositories.
|
||||
form.name_reserved = Repository name '%s' is reserved.
|
||||
form.name_pattern_not_allowed = Repository name pattern '%s' is not allowed.
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied = You are not allowed to import local repositories.
|
||||
migrate.invalid_local_path = Invalid local path, it does not exist or not a directory.
|
||||
migrate.failed = Migration failed: %v
|
||||
|
||||
mirror_from = mirror from
|
||||
forked_from = forked from
|
||||
fork_from_self = You cannot fork a repository you already own!
|
||||
copy_link = Copy
|
||||
@@ -506,9 +513,9 @@ pulls.merged = Merged
|
||||
pulls.has_merged = This pull request has been merged successfully!
|
||||
pulls.data_broken = Data of this pull request has been broken due to deletion of fork information.
|
||||
pulls.is_checking = The conflict checking is still in progress, please refresh page in few moments.
|
||||
pulls.can_auto_merge_desc = You can perform auto-merge operation on this pull request.
|
||||
pulls.cannot_auto_merge_desc = You can't perform auto-merge operation because there are conflicts between commits.
|
||||
pulls.cannot_auto_merge_helper = Please use command line tool to solve it.
|
||||
pulls.can_auto_merge_desc = This pull request can be merged automatically.
|
||||
pulls.cannot_auto_merge_desc = This pull request can't be merged automatically because there are conflicts.
|
||||
pulls.cannot_auto_merge_helper = Please merge manually in order to resolve the conflicts.
|
||||
pulls.merge_pull_request = Merge Pull Request
|
||||
pulls.open_unmerged_pull_exists = `You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
|
||||
|
||||
@@ -563,6 +570,9 @@ settings.update_settings = Update Settings
|
||||
settings.change_reponame_prompt = This change will affect how links relate to the repository.
|
||||
settings.advanced_settings = Advanced Settings
|
||||
settings.wiki_desc = Enable wiki to allow people write documents
|
||||
settings.use_external_wiki = Use external wiki
|
||||
settings.external_wiki_url = External Wiki URL
|
||||
settings.external_wiki_url_desc = Visitors will be redirected to URL when they click on the tab.
|
||||
settings.issues_desc = Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker = Use external issue tracker
|
||||
settings.tracker_url_format = External Issue Tracker URL Format
|
||||
@@ -600,7 +610,7 @@ settings.webhook_deletion_desc = Delete this webhook will remove its information
|
||||
settings.webhook_deletion_success = Webhook has been deleted successfully!
|
||||
settings.webhook.test_delivery = Test Delivery
|
||||
settings.webhook.test_delivery_desc = Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success = Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.test_delivery_success = Test webhook has been added to delivery queue. It may take few seconds before it shows up in the delivery history.
|
||||
settings.webhook.request = Request
|
||||
settings.webhook.response = Response
|
||||
settings.webhook.headers = Headers
|
||||
@@ -826,7 +836,7 @@ dashboard.mspan_structures_obtained = MSpan Structures Obtained
|
||||
dashboard.mcache_structures_usage = MCache Structures Usage
|
||||
dashboard.mcache_structures_obtained = MCache Structures Obtained
|
||||
dashboard.profiling_bucket_hash_table_obtained = Profiling Bucket Hash Table Obtained
|
||||
dashboard.gc_metadata_obtained = GC Metadada Obtained
|
||||
dashboard.gc_metadata_obtained = GC Metadata Obtained
|
||||
dashboard.other_system_allocation_obtained = Other System Allocation Obtained
|
||||
dashboard.next_gc_recycle = Next GC Recycle
|
||||
dashboard.last_gc_time = Since Last GC Time
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name = Authentication Login Name
|
||||
users.password_helper = Leave it empty to remain unchanged.
|
||||
users.update_profile_success = Account profile has been updated successfully.
|
||||
users.edit_account = Edit Account
|
||||
users.max_repo_creation = Maximum Repository Creation Limit
|
||||
users.max_repo_creation_desc = (Set -1 to use global default limit)
|
||||
users.is_activated = This account is activated
|
||||
users.is_admin = This account has administrator permissions
|
||||
users.allow_git_hook = This account has permissions to create Git hooks
|
||||
@@ -1018,7 +1030,7 @@ comment_issue = `commented on issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
merge_pull_request = `merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo = transfered repository <code>%s</code> to <a href="%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_commits = View comparison for these %d commits
|
||||
|
||||
[tool]
|
||||
ago = ago
|
||||
@@ -1044,5 +1056,5 @@ raw_minutes = minutes
|
||||
[dropzone]
|
||||
default_message = Drop files here or click to upload.
|
||||
invalid_input_type = You can't upload files of this type.
|
||||
file_too_big = File size({{filesize}} MB) exceeds maximum size({{maxFilesize}} MB).
|
||||
file_too_big = File size ({{filesize}} MB) exceeds maximum size ({{maxFilesize}} MB).
|
||||
remove_file = Remove file
|
||||
|
||||
@@ -28,6 +28,7 @@ organization=Organización
|
||||
mirror=Mirror
|
||||
new_repo=Nuevo repositorio
|
||||
new_migrate=Nueva Migración
|
||||
new_mirror=Nueva réplica
|
||||
new_fork=Nuevo Fork del Repositorio
|
||||
new_org=Nueva organización
|
||||
manage_org=Administrar organizaciones
|
||||
@@ -242,11 +243,12 @@ ssh_keys=Claves SSH
|
||||
social=Redes Sociales
|
||||
applications=Aplicaciones
|
||||
orgs=Organizaciones
|
||||
delete=Eliminar Cuenta
|
||||
delete=Eliminar cuenta
|
||||
uid=UUID
|
||||
|
||||
public_profile=Perfil Público
|
||||
profile_desc=Tu correo electrónico es público y será usado para todas las notificaciones relacionadas con cualquier cuenta y cualquier operación hecha a través de la web.
|
||||
password_username_disabled=Los usuarios que no son locales no tienen permitido cambiar su nombre de usuario.
|
||||
full_name=Nombre Completo
|
||||
website=Página Web
|
||||
location=Localización
|
||||
@@ -271,6 +273,7 @@ new_password=Nueva contraseña
|
||||
retype_new_password=Confirmar nueva contraseña
|
||||
password_incorrect=Contraseña actual incorrecta.
|
||||
change_password_success=La contraseña se ha modificado correctamente. Ya puedes iniciar sesión con tu nueva contraseña.
|
||||
password_change_disabled=Los usuarios que no son locales no tienen permitido cambiar su contraseña.
|
||||
|
||||
emails=Direcciones de correo electrónico
|
||||
manage_emails=Gestionar direcciones de correo electrónico
|
||||
@@ -279,7 +282,7 @@ primary=Principal
|
||||
primary_email=Marcar como principal
|
||||
delete_email=Eliminar
|
||||
email_deletion=Eliminación de Correo Electrónico
|
||||
email_deletion_desc=Al eliminar esta dirección de correo electrónico se eliminará toda la información asociada a esta dirección de correo electrónico. ¿Deseas continuar?
|
||||
email_deletion_desc=Al eliminar esta dirección de correo electrónico se eliminará toda la información asociada a esta. ¿Deseas continuar?
|
||||
email_deletion_success=¡El correo electrónico ha sido eliminado correctamente!
|
||||
add_new_email=Añadir nueva dirección de correo electrónico
|
||||
add_email=Añadir correo electrónico
|
||||
@@ -352,10 +355,13 @@ auto_init=Inicializar los archivos seleccionados y plantillas de este repositori
|
||||
create_repo=Crear Repositorio
|
||||
default_branch=Rama por defecto
|
||||
mirror_interval=Intervalo de mirror(en horas)
|
||||
mirror_address=Dirección de la réplica
|
||||
mirror_address_desc=Por favor, incluya las credenciales de usuario necesarias en la dirección.
|
||||
watchers=Seguidores
|
||||
stargazers=Fans
|
||||
forks=Forks
|
||||
|
||||
form.reach_limit_of_creation=El propietario ha alcanzado el límite máximo de %d repositorios creados.
|
||||
form.name_reserved=El nombre del repositorio '%s' está reservado.
|
||||
form.name_pattern_not_allowed=El patrón del nombre del repositorio '%s' no está permitido.
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied=No te está permitido importar repositorios locales.
|
||||
migrate.invalid_local_path=Rutal local inválida, no existe o no es un directorio.
|
||||
migrate.failed=Migración fallida: %v
|
||||
|
||||
mirror_from=espejo de
|
||||
forked_from=forked de
|
||||
fork_from_self=Eres el propietario del repositorio, ¡no puedes hacer fork!
|
||||
copy_link=Copiar
|
||||
@@ -506,9 +513,9 @@ pulls.merged=Fuisionado
|
||||
pulls.has_merged=¡Este pull request se ha completado con éxito!
|
||||
pulls.data_broken=Los datos de este pull request ya no están disponibles porque se ha eliminado la información del fork.
|
||||
pulls.is_checking=Se está procediendo a la búsqueda de conflictos, por favor actualice la página en unos momentos.
|
||||
pulls.can_auto_merge_desc=Puede realizar la operación auto-fusionado en este pull request.
|
||||
pulls.cannot_auto_merge_desc=No puede realizar la operación de auto-fusionado porque existen conflictos entre los commits.
|
||||
pulls.cannot_auto_merge_helper=Por favor use la línea de comandos para resolverlo.
|
||||
pulls.can_auto_merge_desc=Este Pull Request puede ser fusionado automáticamente.
|
||||
pulls.cannot_auto_merge_desc=Este Pull Request no puede ser fusionado automáticamente porque hay conflictos.
|
||||
pulls.cannot_auto_merge_helper=Por favor, fusiona manualmente para resolver los conflictos.
|
||||
pulls.merge_pull_request=Fusionar Pull Request
|
||||
pulls.open_unmerged_pull_exists=`Usted no puede realizar la operación de reapertura porque en estos momentos existe una solicitud de pull request (#%d) para el mismo repositorio con la misma información que se encuentra a la espera de aprobación`
|
||||
|
||||
@@ -559,15 +566,18 @@ settings.hooks=Webhooks
|
||||
settings.githooks=Git Hooks
|
||||
settings.basic_settings=Configuración Básica
|
||||
settings.site=Sitio Oficial
|
||||
settings.update_settings=Actualizar Configuración
|
||||
settings.update_settings=Actualizar configuración
|
||||
settings.change_reponame_prompt=Este cambio afectará a los enlaces al repositorio.
|
||||
settings.advanced_settings=Ajustes avanzados
|
||||
settings.wiki_desc=Habilitar a las personas en la Wiki a que puedan escribir documentos
|
||||
settings.issues_desc=Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Use external issue tracker
|
||||
settings.tracker_url_format=External Issue Tracker URL Format
|
||||
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc=Enable pull requests to accept public contributions
|
||||
settings.wiki_desc=Habilitar la Wiki para que los colaboradores documenten
|
||||
settings.use_external_wiki=Usar Wiki externa
|
||||
settings.external_wiki_url=URL externa de la Wiki
|
||||
settings.external_wiki_url_desc=Los visitantes serán redireccionados a la URL cuando hagan click en la barra.
|
||||
settings.issues_desc=Habilitar tracker ligero de incidencias
|
||||
settings.use_external_issue_tracker=Usar tracker externo de incidencias
|
||||
settings.tracker_url_format=Formato URL del tracker de incidencias externo
|
||||
settings.tracker_url_format_desc=Puedes usar las plantillas <code>{user} {repo} {index}</code> para el nombre de usuario, nombre del repositorio e índice de la incidencia.
|
||||
settings.pulls_desc=Habilitar Pull Requests para aceptar contribuciones públicas
|
||||
settings.danger_zone=Zona de Peligro
|
||||
settings.transfer=Transferir la Propiedad
|
||||
settings.transfer_desc=Transferir este repositorio a otro usuario u organización donde tengas permisos de administración.
|
||||
@@ -598,9 +608,9 @@ settings.hooks_desc=Los Webhooks permiten a servicios externos recibir notificac
|
||||
settings.webhook_deletion=Eliminar Webhook
|
||||
settings.webhook_deletion_desc=Al borrar este webhook se eliminará su información y todo su historial. ¿Desea continuar?
|
||||
settings.webhook_deletion_success=¡Webhook eliminado con éxito!
|
||||
settings.webhook.test_delivery=Test Delivery
|
||||
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.test_delivery=Test de entrega
|
||||
settings.webhook.test_delivery_desc=Enviar un falso evento Push de entrega para probar tus ajustes de webhook
|
||||
settings.webhook.test_delivery_success=Probar que los webhook han sido añadidos a la cola de entrega. Esto puede tomar algunos segundos antes de aparecer en el historial de entregas.
|
||||
settings.webhook.request=Petición
|
||||
settings.webhook.response=Respuesta
|
||||
settings.webhook.headers=Encabezado
|
||||
@@ -640,7 +650,7 @@ settings.slack_domain=Dominio
|
||||
settings.slack_channel=Canal
|
||||
settings.deploy_keys=Claves de Despliegue
|
||||
settings.add_deploy_key=Añadir Clave de Despliegue
|
||||
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys.
|
||||
settings.deploy_key_desc=La clave de desarrollo tiene sólo acceso de lectura. No es igual que las claves SSH de las cuentas personales.
|
||||
settings.no_deploy_keys=No has añadido ninguna clave de despliegue.
|
||||
settings.title=Título
|
||||
settings.deploy_key_content=Contenido
|
||||
@@ -686,7 +696,7 @@ release.save_draft=Guardar Borrador
|
||||
release.edit_release=Editar Release
|
||||
release.delete_release=Borrar este Release
|
||||
release.deletion=Eliminación de Release
|
||||
release.deletion_desc=Al eliminar este release se eliminará la etiqueta correspondiente. ¿Desea continuar?
|
||||
release.deletion_desc=Eliminar este Release eliminará la etiqueta correspondiente. ¿Desea continuar?
|
||||
release.deletion_success=¡El release ha sido eliminado correctamente!
|
||||
release.tag_name_already_exist=Ya existe una Release con esta etiqueta.
|
||||
release.downloads=Descargas
|
||||
@@ -718,12 +728,12 @@ settings.options=Opciones
|
||||
settings.full_name=Nombre Completo
|
||||
settings.website=Página Web
|
||||
settings.location=Localización
|
||||
settings.update_settings=Actualizar Configuración
|
||||
settings.update_setting_success=La configuración de la Organización se ha actualizado correctamente.
|
||||
settings.update_settings=Actualizar configuración
|
||||
settings.update_setting_success=La configuración de la organización se ha actualizado correctamente.
|
||||
settings.change_orgname_prompt=Este cambio afectará a los enlaces que hacen referencia a la organización.
|
||||
settings.update_avatar_success=La configuración de avatar de la organización ha sido actualizada con éxito.
|
||||
settings.delete=Eliminar Organización
|
||||
settings.delete_account=Eliminar esta Organización
|
||||
settings.delete=Eliminar organización
|
||||
settings.delete_account=Eliminar esta organización
|
||||
settings.delete_prompt=Esta operación eliminará esta organización de manera permanente, y ¡<strong>NO PUEDE</strong> deshacerse!
|
||||
settings.confirm_delete_account=Confirmar Eliminación
|
||||
settings.delete_org_title=Eliminación de la Organización
|
||||
@@ -755,7 +765,7 @@ teams.no_desc=Este equipo no tiene descripción
|
||||
teams.settings=Configuración
|
||||
teams.owners_permission_desc=Los propietarios tienen acceso completo a <strong>todos los repositorios</strong> y tienen <strong>derechos de administración</strong> en la organización.
|
||||
teams.members=Miembros del Equipo
|
||||
teams.update_settings=Actualizar Configuración
|
||||
teams.update_settings=Actualizar configuración
|
||||
teams.delete_team=Borrar este Equipo
|
||||
teams.add_team_member=Añadir Miembro al Equipo
|
||||
teams.delete_team_title=Eliminar Equipo
|
||||
@@ -805,15 +815,15 @@ dashboard.resync_all_sshkeys_success=Todas las claves públicas se han reescrito
|
||||
dashboard.resync_all_update_hooks=Reescribir todos los hooks de actualización de los repositorios (necesario cuando se modifica la ruta de configuración personalizada)
|
||||
dashboard.resync_all_update_hooks_success=Todos los hooks de actualización de los repositorios se han reescrito correctamente.
|
||||
|
||||
dashboard.server_uptime=Uptime del Servidor
|
||||
dashboard.current_goroutine=Gorutinas Actuales
|
||||
dashboard.current_memory_usage=Uso de Memoria Actual
|
||||
dashboard.server_uptime=Tiempo de actividad del servidor
|
||||
dashboard.current_goroutine=Gorutinas actuales
|
||||
dashboard.current_memory_usage=Uso de memoria actual
|
||||
dashboard.total_memory_allocated=Total de Memoria Reservada
|
||||
dashboard.memory_obtained=Memoria Obtenida
|
||||
dashboard.pointer_lookup_times=Tiempos de Búsqueda de Punteros
|
||||
dashboard.memory_allocate_times=Tiempos de Reserva de Memoria
|
||||
dashboard.memory_free_times=Tiempos de Liberado de Memoria
|
||||
dashboard.current_heap_usage=Uso de Heap Actual
|
||||
dashboard.current_heap_usage=Uso de Heap actual
|
||||
dashboard.heap_memory_obtained=Memoria de Heap Obtenida
|
||||
dashboard.heap_memory_idle=Memoria de Heap Inactiva
|
||||
dashboard.heap_memory_in_use=Memoria de Heap en Uso
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name=Nombre de Inicio de Sesión de Autenticación
|
||||
users.password_helper=Deje el campo vacío si no desea cambiar la contraseña.
|
||||
users.update_profile_success=El perfil de la cuenta se ha actualizado correctamente.
|
||||
users.edit_account=Editar Cuenta
|
||||
users.max_repo_creation=Límite máximo de repositorios
|
||||
users.max_repo_creation_desc=(Configura a -1 para usar el límite global por defecto)
|
||||
users.is_activated=Esta cuenta está activada
|
||||
users.is_admin=Esta cuenta tiene permisos de administrador
|
||||
users.allow_git_hook=Esta cuenta tiene permisos para crear hooks de Git
|
||||
@@ -890,7 +902,7 @@ auths.bind_password=Contraseña Bind
|
||||
auths.bind_password_helper=Advertencia: La contraseña se almacena como texto plano. No utilice una cuenta con privilegios elevados.
|
||||
auths.user_base=Base de Búsqueda de Usuarios
|
||||
auths.user_dn=DN de Usuario
|
||||
auths.attribute_username=Username attribute
|
||||
auths.attribute_username=Atributo de nombre de usuario
|
||||
auths.attribute_username_placeholder=Dejar vacío para usar el campo de inicio de sesión como nombre de usuario.
|
||||
auths.attribute_name=Atributo nombre
|
||||
auths.attribute_surname=Atributo apellido
|
||||
@@ -912,7 +924,7 @@ auths.edit=Editar la Configuración de Autenticación
|
||||
auths.activated=Esta autenticación ha sido activada
|
||||
auths.new_success=¡La autenticación '%s' ha sido añadida con éxito!
|
||||
auths.update_success=La configuración de autenticación ha sido actualizada con éxito.
|
||||
auths.update=Actualizar la Configuración de Autenticación
|
||||
auths.update=Actualizar la configuración de autenticación
|
||||
auths.delete=Eliminar Autenticación
|
||||
auths.delete_auth_title=Borrado de Autenticación
|
||||
auths.delete_auth_desc=Esta autenticación será eliminada. ¿Deseas continuar?
|
||||
@@ -926,7 +938,7 @@ config.domain=Dominio
|
||||
config.offline_mode=Modo Sin Conexión
|
||||
config.disable_router_log=Deshabilitar Log del Router
|
||||
config.run_user=Ejecutada como Usuario
|
||||
config.run_mode=Modo de Ejecución
|
||||
config.run_mode=Modo de ejecución
|
||||
config.repo_root_path=Ruta del Repositorio
|
||||
config.static_file_root_path=Ruta de los Ficheros Estáticos
|
||||
config.log_file_root_path=Ruta de los Ficheros de Log
|
||||
@@ -986,10 +998,10 @@ config.log_mode=Modo del Log
|
||||
monitor.cron=Tareas de Cron
|
||||
monitor.name=Nombre
|
||||
monitor.schedule=Agenda
|
||||
monitor.next=Próxima Vez
|
||||
monitor.previous=Vez Anterior
|
||||
monitor.next=Siguiente
|
||||
monitor.previous=Anterior
|
||||
monitor.execute_times=Ejecuciones
|
||||
monitor.process=Procesos en Ejecución
|
||||
monitor.process=Procesos en ejecución
|
||||
monitor.desc=Descripción
|
||||
monitor.start=Hora de Inicio
|
||||
monitor.execute_time=Tiempo de ejecución
|
||||
@@ -1009,7 +1021,7 @@ notices.op=Op.
|
||||
notices.delete_success=Las notificaciones del sistema han sido eliminadas satisfactoriamente.
|
||||
|
||||
[action]
|
||||
create_repo=repositorio creado <a href="%s">%s</a>
|
||||
create_repo=creó el repositorio <a href="%s">%s</a>
|
||||
rename_repo=repositorio renombrado de <code>%[1]s</code> a <a href="%[2]s">%[3]s</a>
|
||||
commit_repo=hizo push a <a href="%[1]s/src/%[2]s">%[3]s</a> en <a href="%[1]s">%[4]s</a>
|
||||
create_issue=`incidencia abierta <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
@@ -1018,7 +1030,7 @@ comment_issue=`comentó en la incidencia <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
merge_pull_request=`fusionado pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo=transfirió el repositorio <code>%s</code> a <a href="%s">%s</a>
|
||||
push_tag=hizo push del tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
|
||||
compare_2_commits=Ver la comparación de estos 2 commits
|
||||
compare_commits=Ver comparación de estos %d commits
|
||||
|
||||
[tool]
|
||||
ago=hace
|
||||
|
||||
@@ -28,6 +28,7 @@ organization=Organisation
|
||||
mirror=Miroir
|
||||
new_repo=Nouveau Dépôt
|
||||
new_migrate=Nouvelle Migration
|
||||
new_mirror=Nouveau miroir
|
||||
new_fork=Nouvel embranchement
|
||||
new_org=Nouvelle Organisation
|
||||
manage_org=Gérer les Organisations
|
||||
@@ -247,6 +248,7 @@ uid=ID d'Utilisateur
|
||||
|
||||
public_profile=Profil Public
|
||||
profile_desc=Votre adresse e-mail est publique et sera utilisée pour les notifications relatives au compte, ainsi que pour toute opération Web effectuée via le site.
|
||||
password_username_disabled=Les utilisateurs non-locaux n'ont pas le droit de modifier leur nom d'utilisateur.
|
||||
full_name=Nom Complet
|
||||
website=Site Web
|
||||
location=Localisation
|
||||
@@ -271,6 +273,7 @@ new_password=Nouveau Mot de Passe
|
||||
retype_new_password=Retapez le nouveau mot de passe
|
||||
password_incorrect=Mot de passe actuel incorrect.
|
||||
change_password_success=Mot de passe modifié avec succès. Vous pouvez à présent vous connecter avec le nouveau mot de passe.
|
||||
password_change_disabled=Les utilisateurs non-locaux n'ont pas le droit de modifier leur mot de passe.
|
||||
|
||||
emails=Adresses E-mail
|
||||
manage_emails=Gérer les adresses e-mail
|
||||
@@ -352,10 +355,13 @@ auto_init=Initialiser ce dépôt avec le modèle et les fichiers sélectionnés
|
||||
create_repo=Créer un dépôt
|
||||
default_branch=Branche par défaut
|
||||
mirror_interval=Intervalle du miroir (heure)
|
||||
mirror_address=Adresse du miroir
|
||||
mirror_address_desc=Veuillez inclure les informations d'identification nécessaires dans l'adresse.
|
||||
watchers=Observateurs
|
||||
stargazers=Stargazers
|
||||
forks=Embranchements
|
||||
|
||||
form.reach_limit_of_creation=Le propriétaire a atteint le nombre maximal de %d dépôts créés.
|
||||
form.name_reserved=Le nom de dépôt '%s' est réservé.
|
||||
form.name_pattern_not_allowed=Motif '%s' interdit pour les noms de dépôt.
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied=Vous n'êtes pas autorisé à importer des dépôts lo
|
||||
migrate.invalid_local_path=Chemin local non valide, non existant ou n'étant pas un dossier.
|
||||
migrate.failed=Echec de migration: %v
|
||||
|
||||
mirror_from=miroir de
|
||||
forked_from=scindé depuis
|
||||
fork_from_self=Vous nous ne pouvez pas scinder un dépôt que vous possédez déja !
|
||||
copy_link=Copier
|
||||
@@ -506,9 +513,9 @@ pulls.merged=Fusionné
|
||||
pulls.has_merged=Cette Pull Request a été fusionnée avec succès !
|
||||
pulls.data_broken=Les données de cette demande de rattachement ont été compromise en raison de la suppression d'informations sur l'embranchement.
|
||||
pulls.is_checking=La recherche de conflits est toujours en cours, veuillez rafraichir la page dans quelques instants.
|
||||
pulls.can_auto_merge_desc=Vous pouvez effectuer d'opération de fusion automatique sur cette demande de Pull Request.
|
||||
pulls.cannot_auto_merge_desc=Vous ne pouvez effectuer des opération de fusion automatique car il y a des conflits entre les Commits.
|
||||
pulls.cannot_auto_merge_helper=Veuillez utiliser l'outil en ligne de commande pour le résoudre.
|
||||
pulls.can_auto_merge_desc=Cette pull request peut être fusionnée automatiquement.
|
||||
pulls.cannot_auto_merge_desc=Cette pull request ne peut être fusionnée automatiquement à cause de conflits.
|
||||
pulls.cannot_auto_merge_helper=Fusionner manuellement afin de résoudre les conflits.
|
||||
pulls.merge_pull_request=Fusionner la Pull Request
|
||||
pulls.open_unmerged_pull_exists=`Vous ne pouvez effectuer une réouverture car il y a déjà une pull-request ouverte (#%d) depuis le même dépôt avec les mêmes informations de fusion et est en attente de fusion.`
|
||||
|
||||
@@ -563,6 +570,9 @@ settings.update_settings=Valider
|
||||
settings.change_reponame_prompt=Ce changement affectera comment les liens sont reliés avec le dépôt.
|
||||
settings.advanced_settings=Paramètres Avancés
|
||||
settings.wiki_desc=Activer le wiki pour permettre l'écriture de documents
|
||||
settings.use_external_wiki=Utiliser un wiki externe
|
||||
settings.external_wiki_url=URL Wiki externe
|
||||
settings.external_wiki_url_desc=Les visiteurs seront redirigés vers cette URL lorsqu'ils cliqueront sur l'onglet.
|
||||
settings.issues_desc=Activer le bug-tracker léger intégré
|
||||
settings.use_external_issue_tracker=Utiliser un bug-tracker externe
|
||||
settings.tracker_url_format=Format d'URL du bug tracker
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name=Nom d'utilisateur d'authentification
|
||||
users.password_helper=Laissez-le vide pour ne pas changer.
|
||||
users.update_profile_success=Profil mis à jour avec succès.
|
||||
users.edit_account=Modifier le Compte
|
||||
users.max_repo_creation=Nombre maximum de dépôts créés
|
||||
users.max_repo_creation_desc=(Mettre à -1 pour utiliser la limite globale par défaut)
|
||||
users.is_activated=Ce compte est activé
|
||||
users.is_admin=Ce compte possède un niveau d'accès administrateur
|
||||
users.allow_git_hook=Ce compte dispose des autorisations pour créer des crochets de Git
|
||||
@@ -1018,7 +1030,7 @@ comment_issue=`a commenté le problème <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
merge_pull_request=`pull request fusionné le <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo=a transféré le dépôt <code>%s</code> à <a href="%s">%s</a>
|
||||
push_tag=a soumis le tag <a href="%s/src/%s">%[2]s</a> à <a href="%[1]s">%[3]s</a>
|
||||
compare_2_commits=Comparer ces 2 commits
|
||||
compare_commits=Comparer ces %d commits
|
||||
|
||||
[tool]
|
||||
ago=auparavant
|
||||
|
||||
@@ -28,6 +28,7 @@ organization=Organizzazione
|
||||
mirror=Mirror
|
||||
new_repo=Nuovo Repository
|
||||
new_migrate=Nuova Migrazione
|
||||
new_mirror=New Mirror
|
||||
new_fork=Nuovo Fork Repository
|
||||
new_org=Nuova organizzazione
|
||||
manage_org=Gestisci le organizzazioni
|
||||
@@ -247,6 +248,7 @@ uid=Uid
|
||||
|
||||
public_profile=Profilo pubblico
|
||||
profile_desc=Il tuo indirizzo e-mail è pubblico e sarà usato per ogni notifica inerente al tuo account, e per qualsiasi operazione web effettuata attraverso il sito.
|
||||
password_username_disabled=Non-local type users are not allowed to change their username.
|
||||
full_name=Nome Completo
|
||||
website=Sito web
|
||||
location=Posizione
|
||||
@@ -271,6 +273,7 @@ new_password=Nuova Password
|
||||
retype_new_password=Re-inserisci la password
|
||||
password_incorrect=La Password attuale non è corretta.
|
||||
change_password_success=La tua password è stata cambiata con successo. Ora puoi accedere usando la nuova password.
|
||||
password_change_disabled=Non-local type users are not allowed to change their password.
|
||||
|
||||
emails=Indirizzi e-mail
|
||||
manage_emails=Gestisci indirizzi email
|
||||
@@ -352,10 +355,13 @@ auto_init=Initialize this repository with selected files and template
|
||||
create_repo=Crea Repository
|
||||
default_branch=Ramo (Branch) predefinito
|
||||
mirror_interval=Intervallo Mirror (in ore)
|
||||
mirror_address=Mirror Address
|
||||
mirror_address_desc=Please include necessary user credentials in the address.
|
||||
watchers=Watchers
|
||||
stargazers=Stargazers
|
||||
forks=Forks
|
||||
|
||||
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
|
||||
form.name_reserved=Il nome repository %s è riservato.
|
||||
form.name_pattern_not_allowed=La struttura del nome del repository %s non è consentita.
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied=You are not allowed to import local repositories.
|
||||
migrate.invalid_local_path=Percorso locale non valido, non esiste o non è una cartella.
|
||||
migrate.failed=Migration failed: %v
|
||||
|
||||
mirror_from=mirror from
|
||||
forked_from=forkato da
|
||||
fork_from_self=Non puoi forkare il tuo stesso repository!
|
||||
copy_link=Copia
|
||||
@@ -506,9 +513,9 @@ pulls.merged=Merged
|
||||
pulls.has_merged=This pull request has been merged successfully!
|
||||
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
|
||||
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
|
||||
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request.
|
||||
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits.
|
||||
pulls.cannot_auto_merge_helper=Please use command line tool to solve it.
|
||||
pulls.can_auto_merge_desc=This pull request can be merged automatically.
|
||||
pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
|
||||
pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
|
||||
pulls.merge_pull_request=Unisci Pull Request
|
||||
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
|
||||
|
||||
@@ -563,6 +570,9 @@ settings.update_settings=Aggiorna Impostazioni
|
||||
settings.change_reponame_prompt=This change will affect how links relate to the repository.
|
||||
settings.advanced_settings=Advanced Settings
|
||||
settings.wiki_desc=Enable wiki to allow people write documents
|
||||
settings.use_external_wiki=Use external wiki
|
||||
settings.external_wiki_url=External Wiki URL
|
||||
settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
|
||||
settings.issues_desc=Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Use external issue tracker
|
||||
settings.tracker_url_format=External Issue Tracker URL Format
|
||||
@@ -600,7 +610,7 @@ settings.webhook_deletion_desc=Delete this webhook will remove its information a
|
||||
settings.webhook_deletion_success=Webhook has been deleted successfully!
|
||||
settings.webhook.test_delivery=Test Delivery
|
||||
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may take few seconds before it shows up in the delivery history.
|
||||
settings.webhook.request=Request
|
||||
settings.webhook.response=Response
|
||||
settings.webhook.headers=Headers
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name=Authentication Login Name
|
||||
users.password_helper=Leave it empty to remain unchanged.
|
||||
users.update_profile_success=Profilo dell'account aggiornato con successo.
|
||||
users.edit_account=Modifica Account
|
||||
users.max_repo_creation=Maximum Repository Creation Limit
|
||||
users.max_repo_creation_desc=(Set -1 to use global default limit)
|
||||
users.is_activated=Questo account è attivato
|
||||
users.is_admin=Questo account ha permessi di amministratore
|
||||
users.allow_git_hook=Questo account ha il permesso di creare hooks di Git
|
||||
@@ -1018,7 +1030,7 @@ comment_issue=`ha commentato il problema <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo=ha trasferito il repository <code>%s</code> a <a href="%s">%s</a>
|
||||
push_tag=ha pushato il tag <a href="%s/src/%s">%[2]s</a> a <a href="%[1]s">%[3]s</a>
|
||||
compare_2_commits=Vedi confronto per questi 2 commit
|
||||
compare_commits=View comparison for these %d commits
|
||||
|
||||
[tool]
|
||||
ago=fa
|
||||
@@ -1044,6 +1056,6 @@ raw_minutes=minuti
|
||||
[dropzone]
|
||||
default_message=Drop files here or click to upload.
|
||||
invalid_input_type=You can't upload files of this type.
|
||||
file_too_big=File size({{filesize}} MB) exceeds maximum size({{maxFilesize}} MB).
|
||||
file_too_big=File size ({{filesize}} MB) exceeds maximum size ({{maxFilesize}} MB).
|
||||
remove_file=Remove file
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ organization=組織
|
||||
mirror=ミラー
|
||||
new_repo=新しいリポジトリ
|
||||
new_migrate=新しい移行
|
||||
new_mirror=新しいミラー
|
||||
new_fork=新しいフォークのリポジトリ
|
||||
new_org=新しい組織
|
||||
manage_org=組織を管理
|
||||
@@ -67,7 +68,7 @@ path=パス
|
||||
sqlite_helper=SQLite3 または TiDB のデータベースのファイル パス。
|
||||
err_empty_db_path=SQLite3 または TiDB データベースのパスを空にすることはできません。
|
||||
err_invalid_tidb_name=TiDB データベース名は文字"."と"-"を許可しない。
|
||||
no_admin_and_disable_registration=You cannot disable registration without creating an admin account.
|
||||
no_admin_and_disable_registration=管理者アカウントを作成せずに登録を無効にすることはできません。
|
||||
err_empty_admin_password=管理者パスワードは空白にできません。
|
||||
|
||||
general_title=Gogs の全般設定
|
||||
@@ -247,6 +248,7 @@ uid=Uid
|
||||
|
||||
public_profile=パブリック プロフィール
|
||||
profile_desc=あなたのメールアドレスは公開され、任意のアカウント関連の通知に使用されます。また、Webベースの操作はサイトを介して行います。
|
||||
password_username_disabled=ローカルユーザ以外はユーザ名を変更できません。
|
||||
full_name=フルネーム
|
||||
website=WEBサイト
|
||||
location=ロケーション
|
||||
@@ -271,6 +273,7 @@ new_password=新しいパスワード
|
||||
retype_new_password=新しいパスワードを再入力します。
|
||||
password_incorrect=現在のパスワードが正しくありません。
|
||||
change_password_success=パスワードが正常に変更されました。今すぐ新しいパスワード経由でサインインすることができます。
|
||||
password_change_disabled=ローカルユーザ以外はパスワードを変更できません。
|
||||
|
||||
emails=E-mail アドレス
|
||||
manage_emails=E-mail アドレスを管理
|
||||
@@ -352,10 +355,13 @@ auto_init=選択されたファイルおよびテンプレートでリポジト
|
||||
create_repo=リポジトリを作成
|
||||
default_branch=デフォルトのブランチ
|
||||
mirror_interval=ミラー 間隔(時)
|
||||
mirror_address=ミラー アドレス
|
||||
mirror_address_desc=Please include necessary user credentials in the address.
|
||||
watchers=ウォッチャー
|
||||
stargazers=Stargazers
|
||||
forks=フォーク
|
||||
|
||||
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
|
||||
form.name_reserved=リポジトリ名 '%s' は予約されています。
|
||||
form.name_pattern_not_allowed=リポジトリ名のパターン '%s' は許可されていません。
|
||||
|
||||
@@ -367,8 +373,9 @@ migrate.clone_address=クローンアドレス
|
||||
migrate.clone_address_desc=これは、HTTP/HTTPS/GIT URL またはローカル サーバー パスを設定できます。
|
||||
migrate.permission_denied=ローカル リポジトリをインポートすることはできません。
|
||||
migrate.invalid_local_path=ローカルパスが無効です。存在しないかディレクトリではありません。
|
||||
migrate.failed=Migration failed: %v
|
||||
migrate.failed=移行に失敗しました: %v
|
||||
|
||||
mirror_from=mirror from
|
||||
forked_from=フォーク元
|
||||
fork_from_self=すでにあなたの所有しているリポジトリはフォークできません
|
||||
copy_link=コピー
|
||||
@@ -388,7 +395,7 @@ create_new_repo_command=コマンドラインで新しいリポジトリを作
|
||||
push_exist_repo=コマンド ・ ラインから既存のリポジトリをプッシュ
|
||||
repo_is_empty=このリポジトリは空です、後で戻って来て下さい!
|
||||
|
||||
code=Code
|
||||
code=コード
|
||||
branch=ブランチ
|
||||
tree=ツリー
|
||||
filter_branch_and_tag=ブランチまたはタグをフィルタリング
|
||||
@@ -457,7 +464,7 @@ issues.next=次ページ
|
||||
issues.open_title=オープン
|
||||
issues.closed_title=クローズ
|
||||
issues.num_comments=%d コメント
|
||||
issues.commented_at=`commented <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=`コメント <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.no_content=まだコンテンツがありません
|
||||
issues.close_issue=閉じる
|
||||
issues.close_comment_issue=コメントと閉じる
|
||||
@@ -506,9 +513,9 @@ pulls.merged=マージされた
|
||||
pulls.has_merged=このプルプルリクエストは正常にマージされました!
|
||||
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
|
||||
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
|
||||
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request.
|
||||
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits.
|
||||
pulls.cannot_auto_merge_helper=それを解決するためにコマンド ライン ツールを使用してください。
|
||||
pulls.can_auto_merge_desc=This pull request can be merged automatically.
|
||||
pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
|
||||
pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
|
||||
pulls.merge_pull_request=プルリクエストをマージします。
|
||||
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
|
||||
|
||||
@@ -541,7 +548,7 @@ wiki.welcome=Wiki へようこそ!
|
||||
wiki.welcome_desc=Wiki is the place where you would like to document your project together and make it better.
|
||||
wiki.create_first_page=最初のページを作成する。
|
||||
wiki.page=ページ
|
||||
wiki.filter_page=Filter page
|
||||
wiki.filter_page=フィルターページ
|
||||
wiki.new_page=新しいページを作成
|
||||
wiki.default_commit_message=このアップデートについてメモを書く(オプション)
|
||||
wiki.save_page=ページを保存
|
||||
@@ -561,11 +568,14 @@ settings.basic_settings=基本設定
|
||||
settings.site=公式サイト
|
||||
settings.update_settings=設定の更新
|
||||
settings.change_reponame_prompt=この変更はリンクがリポジトリに関連付ける方法に影響します。
|
||||
settings.advanced_settings=Advanced Settings
|
||||
settings.advanced_settings=拡張設定
|
||||
settings.wiki_desc=Enable wiki to allow people write documents
|
||||
settings.use_external_wiki=外部 wiki を使用します。
|
||||
settings.external_wiki_url=外部 Wiki の URL
|
||||
settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
|
||||
settings.issues_desc=Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Use external issue tracker
|
||||
settings.tracker_url_format=External Issue Tracker URL Format
|
||||
settings.use_external_issue_tracker=外部課題トラッキングシステムを使用
|
||||
settings.tracker_url_format=外部課題トラッキングツール URLのフォーマット
|
||||
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc=Enable pull requests to accept public contributions
|
||||
settings.danger_zone=危険地帯
|
||||
@@ -577,7 +587,7 @@ settings.delete_desc=リポジトリを削除すると元に戻せません。
|
||||
settings.transfer_notices_1=-新しい所有者が個人ユーザーの場合、あなたがアクセスできなくなります。
|
||||
settings.transfer_notices_2=- You will conserve access if new owner is an organization and if you're one of the owners.
|
||||
settings.transfer_form_title=操作を確認するために、以下の情報を入力してください。
|
||||
settings.delete_notices_1=- This operation <strong>CANNOT</strong> be undone.
|
||||
settings.delete_notices_1=-この操作は<strong>元に戻せません</strong> 。
|
||||
settings.delete_notices_2=- This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators.
|
||||
settings.delete_notices_fork_1=- If this repository is public, all forks will be became independent after deletion.
|
||||
settings.delete_notices_fork_2=- If this repository is private, all forks will be removed at the same time.
|
||||
@@ -598,9 +608,9 @@ settings.hooks_desc=Webhooksは、Gogsで特定のイベントの発生時に指
|
||||
settings.webhook_deletion=Webhook を削除
|
||||
settings.webhook_deletion_desc=このwebhookを削除すると、すべての情報と配信履歴が削除されます。続行しますか?
|
||||
settings.webhook_deletion_success=Webhook が正常に削除されました。
|
||||
settings.webhook.test_delivery=Test Delivery
|
||||
settings.webhook.test_delivery=テスト配信
|
||||
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may take few seconds before it shows up in the delivery history.
|
||||
settings.webhook.request=リクエスト
|
||||
settings.webhook.response=レスポンス
|
||||
settings.webhook.headers=ヘッダ
|
||||
@@ -640,7 +650,7 @@ settings.slack_domain=ドメイン
|
||||
settings.slack_channel=チャンネル
|
||||
settings.deploy_keys=デプロイキー
|
||||
settings.add_deploy_key=デプロイキーを追加
|
||||
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys.
|
||||
settings.deploy_key_desc=個人アカウントのSSHキーとは異なり、デプロイキーは読み取り専用アクセスとなります。
|
||||
settings.no_deploy_keys=でプロキーは1つも追加されていません。
|
||||
settings.title=タイトル
|
||||
settings.deploy_key_content=コンテント
|
||||
@@ -669,7 +679,7 @@ release.edit=編集
|
||||
release.ahead=このリリース以降 %s へ <strong>%d</strong> コミット
|
||||
release.source_code=ソース コード
|
||||
release.new_subheader=Publish releases to iterate product.
|
||||
release.edit_subheader=Detailed change log can help users understand what has been improved.
|
||||
release.edit_subheader=詳細な変更ログは、ユーザーに何が改善されたかの理解を助けることができます。
|
||||
release.tag_name=タグ名
|
||||
release.target=ターゲット
|
||||
release.tag_helper=既存のタグを選択するか、新しいタグを作成し発行します。
|
||||
@@ -721,7 +731,7 @@ settings.location=ロケーション
|
||||
settings.update_settings=設定の更新
|
||||
settings.update_setting_success=組織の設定が更新されました。
|
||||
settings.change_orgname_prompt=This change will affect how links relate to the organization.
|
||||
settings.update_avatar_success=Organization avatar setting has been updated successfully.
|
||||
settings.update_avatar_success=組織のアバター画像が正常に更新されました。
|
||||
settings.delete=組織を削除
|
||||
settings.delete_account=この組織を削除
|
||||
settings.delete_prompt=操作はこの組織を完全に削除し、復旧<strong>できない</strong>!
|
||||
@@ -796,7 +806,7 @@ dashboard.delete_inactivate_accounts=非アクティブのアカウントをす
|
||||
dashboard.delete_inactivate_accounts_success=すべての非アクティブアカウントは正常に削除されました。
|
||||
dashboard.delete_repo_archives=リポジトリのすべてのアーカイブを削除
|
||||
dashboard.delete_repo_archives_success=リポジトリのすべてのアーカイブが正常に削除されました。
|
||||
dashboard.delete_missing_repos=Delete all repository records that lost Git files
|
||||
dashboard.delete_missing_repos=Gitファイルが失われたリポジトリのすべてのレコードを削除
|
||||
dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully.
|
||||
dashboard.git_gc_repos=リポジトリでのガベージコレクションを実行します。
|
||||
dashboard.git_gc_repos_success=すべてのリポジトリは正常にガベージ コレクションを行いました。
|
||||
@@ -843,7 +853,7 @@ users.admin=アドミン
|
||||
users.repos=リポジトリ
|
||||
users.created=作成されました
|
||||
users.send_register_notify=登録通知をユーザーに送信
|
||||
users.new_success=New account '%s' has been created successfully.
|
||||
users.new_success=新規アカウント '%s' が正常に作成されました。
|
||||
users.edit=編集
|
||||
users.auth_source=認証ソース
|
||||
users.local=ローカル
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name=認証ログイン名
|
||||
users.password_helper=それをそのまま空のままにします。
|
||||
users.update_profile_success=アカウントのプロファイルが更新されました。
|
||||
users.edit_account=アカウントの編集
|
||||
users.max_repo_creation=Maximum Repository Creation Limit
|
||||
users.max_repo_creation_desc=(Set -1 to use global default limit)
|
||||
users.is_activated=アカウントがアクティブされました
|
||||
users.is_admin=このアカウントには管理者の権限を持つ
|
||||
users.allow_git_hook=このアカウントには Git のフックを作成する権限を持つ
|
||||
@@ -995,18 +1007,18 @@ monitor.start=開始日時
|
||||
monitor.execute_time=実行時間:
|
||||
|
||||
notices.system_notice_list=システム通知
|
||||
notices.view_detail_header=View Notice Detail
|
||||
notices.actions=Actions
|
||||
notices.select_all=Select All
|
||||
notices.deselect_all=Deselect All
|
||||
notices.inverse_selection=Inverse Selection
|
||||
notices.delete_selected=Delete Selected
|
||||
notices.delete_all=Delete All Notices
|
||||
notices.view_detail_header=お知らせの詳細を表示
|
||||
notices.actions=アクション
|
||||
notices.select_all=全て選択
|
||||
notices.deselect_all=すべて選択解除
|
||||
notices.inverse_selection=反転
|
||||
notices.delete_selected=選択項目を削除
|
||||
notices.delete_all=すべての通知を削除
|
||||
notices.type=タイプ
|
||||
notices.type_1=リポジトリ
|
||||
notices.desc=説明
|
||||
notices.op=Op。
|
||||
notices.delete_success=System notices have been deleted successfully.
|
||||
notices.delete_success=システム通知が正常に削除されました。
|
||||
|
||||
[action]
|
||||
create_repo=リポジトリ <a href="%s"> %s</a>を作成しました
|
||||
@@ -1018,7 +1030,7 @@ comment_issue=`問題 <a href="%s/issues/%s">%s#%[2]s</a> のコメント`
|
||||
merge_pull_request=`プルリクエスト <a href="%s/pulls/%s"> %s[2]s</a>をマージしました`
|
||||
transfer_repo=リポジトリ <code>%s</code> を <a href="%s">%s</a> へ転送しました
|
||||
push_tag=<a href="%[1]s">%[3]s</a> に タグ <a href="%[1]s/src/%[2]s">%[2]s</a> をプッシュしました
|
||||
compare_2_commits=これら 2 のコミットの比較を閲覧する
|
||||
compare_commits=これらの %d コミットの比較を表示
|
||||
|
||||
[tool]
|
||||
ago=前
|
||||
|
||||
@@ -28,6 +28,7 @@ organization=Organizācija
|
||||
mirror=Spogulis
|
||||
new_repo=Jauns repozitorijs
|
||||
new_migrate=Jauna migrācija
|
||||
new_mirror=Jauns spogulis
|
||||
new_fork=Jauns atdalītais repozitorijs
|
||||
new_org=Jauna organizācija
|
||||
manage_org=Pārvaldīt organizācijas
|
||||
@@ -247,6 +248,7 @@ uid=Lietotāja ID
|
||||
|
||||
public_profile=Publiskais profils
|
||||
profile_desc=Jūsu e-pasta adrese ir publiska un tiks izmantota, lai nosūtītju Jums paziņojumus, kas saistīti ar Jūsu kontu vai darbībām veiktām caur šo mājas lapu.
|
||||
password_username_disabled=Ne-lokālie lietotāji nevar mainīt savus lietotājvārdus.
|
||||
full_name=Pilns vārds
|
||||
website=Mājas lapa
|
||||
location=Atrašanās vieta
|
||||
@@ -271,6 +273,7 @@ new_password=Jauna parole
|
||||
retype_new_password=Ievadīt paroli atkāroti
|
||||
password_incorrect=Ievadīta nepareiza pašreizējā parole.
|
||||
change_password_success=Parole tika veiksmīgi nomainīta. Tagad jūs varat pieraksītites, izmantojot jauno paroli.
|
||||
password_change_disabled=Ne-lokālie lietotāji nevar mainīt savas paroles.
|
||||
|
||||
emails=E-pasta adreses
|
||||
manage_emails=Pārvaldīt e-pasta adreses
|
||||
@@ -352,10 +355,13 @@ auto_init=Inicializēt šo repozitoriju ar izvēlētajiem failiem un sagatavi
|
||||
create_repo=Izveidot repozitoriju
|
||||
default_branch=Noklusējuma atzars
|
||||
mirror_interval=Spoguļošanas intervāls (stundās)
|
||||
mirror_address=Spoguļa adrese
|
||||
mirror_address_desc=Lūdzu iekļaujiet adresē nepieciešamo lietotājvārdu/paroli.
|
||||
watchers=Novērotāji
|
||||
stargazers=Zvaigžņdevēji
|
||||
forks=Atdalītie repozitoriji
|
||||
|
||||
form.reach_limit_of_creation=Īpašnieks sasniedza maksimālu pieļaujamo (%d) izveidoto repozitoriju skaitu.
|
||||
form.name_reserved=Repozitorija nosaukums '%s' ir rezervēts.
|
||||
form.name_pattern_not_allowed=Repozitorija nosaukums '%s' nav atļauts.
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied=Jums nav tiesību importēt lokālu repozitoriju.
|
||||
migrate.invalid_local_path=Nekorents lokālais ceļš, tas neeksistē vai nav direktorijs.
|
||||
migrate.failed=Migrācija neizdevās: %v
|
||||
|
||||
mirror_from=spogulis no
|
||||
forked_from=atdalīts no
|
||||
fork_from_self=Nav iespējams atdalīt repozitoriju, kuram esat īpašnieks!
|
||||
copy_link=Kopēt
|
||||
@@ -388,7 +395,7 @@ create_new_repo_command=Izveidot jaunu repozitoriju komandrindā
|
||||
push_exist_repo=Nosūtīt izmaiņas no komandrindas eksistējošam repozitorijam
|
||||
repo_is_empty=Šis repozitorijs ir tukšs, apskatiet atkal vēlāk!
|
||||
|
||||
code=Code
|
||||
code=Kods
|
||||
branch=Atzars
|
||||
tree=Koks
|
||||
filter_branch_and_tag=Filtrēt atzarus vai tagus
|
||||
@@ -506,9 +513,9 @@ pulls.merged=Sapludināts
|
||||
pulls.has_merged=Šo izmaiņu pieprasījums tika veiksmīgi sapludināts!
|
||||
pulls.data_broken=Nepieejami izmaiņu pieprasījuma dati, jo dzēsta informācija no atdalītā repozitorija.
|
||||
pulls.is_checking=Notiek konfliktu pārbaude, mirkli uzgaidiet un atjaunojiet lapu.
|
||||
pulls.can_auto_merge_desc=Ir iespējams veikt automātisko sapludināšanas darbību šim izmaiņu pieprasījumam.
|
||||
pulls.cannot_auto_merge_desc=Nav iespējams veikt automātisko sapludināšanas darbību, jo starp revīzijām ir konflikti.
|
||||
pulls.cannot_auto_merge_helper=Lūdzu, izmantojiet komandrindas rīku, lai to atrisinātu.
|
||||
pulls.can_auto_merge_desc=Šo izmaiņu pieprasījumu var automātiski saplūdināt.
|
||||
pulls.cannot_auto_merge_desc=Šis izmaiņu pieprasījums nevar tikt automātiski saplūdināts konfliktu dēļ.
|
||||
pulls.cannot_auto_merge_helper=Lūdzu sapludiniet manuāli, lai atrisinātu konfliktus.
|
||||
pulls.merge_pull_request=Izmaiņu pieprasījuma sapludināšana
|
||||
pulls.open_unmerged_pull_exists=`Jūs nevarat veikt atkārtotas atvēršanas darbību, jo jau eksistē izmaiņu pieprasījums (#%d) no šī repozitorija ar tādu pašu sapludināšanas informāciju un gaida sapludināšanu.`
|
||||
|
||||
@@ -561,13 +568,16 @@ settings.basic_settings=Pamatiestatījumi
|
||||
settings.site=Oficiālā mājas lapa
|
||||
settings.update_settings=Mainīt iestatījumus
|
||||
settings.change_reponame_prompt=Šī izmaiņa ietekmēs saites, kas ir saistītas ar šo repozitoriju.
|
||||
settings.advanced_settings=Advanced Settings
|
||||
settings.wiki_desc=Enable wiki to allow people write documents
|
||||
settings.issues_desc=Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Use external issue tracker
|
||||
settings.tracker_url_format=External Issue Tracker URL Format
|
||||
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc=Enable pull requests to accept public contributions
|
||||
settings.advanced_settings=Papildu iestatījumi
|
||||
settings.wiki_desc=Iespējot vikivietni, lai atļautu cilvēkiem rakstīt dokumentus
|
||||
settings.use_external_wiki=Izmantot ārējo vikivietni
|
||||
settings.external_wiki_url=Ārējās Vikivietnes adrese
|
||||
settings.external_wiki_url_desc=Apmeklētāji tiks novirzīti uz adresi, kad viņi uzklikšķinās uz cilnes.
|
||||
settings.issues_desc=Iespējot iebūvētu vieglu problēmu sekotāju
|
||||
settings.use_external_issue_tracker=Izmantot ārējo problēmu sekotāju
|
||||
settings.tracker_url_format=Ārējā problēmu sekotāja adreses formāts
|
||||
settings.tracker_url_format_desc=Jūs varat izmantot <code>{user}{repo}{index}</code> lietotājvārdam, repozitorija nosaukumam un problēmas identifikātoram.
|
||||
settings.pulls_desc=Iespējot izmaiņu pieprasījumus lai saņemtu publiskus ieguldījumus
|
||||
settings.danger_zone=Bīstamā zona
|
||||
settings.transfer=Mainīt īpašnieku
|
||||
settings.transfer_desc=Mainīt šī repozitorija īpašnieku uz citu lietotāju vai organizāciju, kurai Jums ir administratora tiesībs.
|
||||
@@ -582,7 +592,7 @@ settings.delete_notices_2=- Šī darbība neatgriezeniski izdzēsīs visus šī
|
||||
settings.delete_notices_fork_1=- Ja repozitorijs ir publisks, visi atdalītie repozitoriji kļūs neatkarīgi.
|
||||
settings.delete_notices_fork_2=- Ja repozitorijs ir privāts, tiks dzēsti arī visi atdalītie repozitoriji.
|
||||
settings.delete_notices_fork_3=- Ja vēlaties saglabāt atdalīts repozitorijus pēc dzēšanas, sākumā nomainiet repozitorija redzamību uz publisku.
|
||||
settings.deletion_success=Repository has been deleted successfully!
|
||||
settings.deletion_success=Repozitorijs tika veiksmīgi dzēsts!
|
||||
settings.update_settings_success=Repozitorija opcijas ir veiksmīgi saglabātas.
|
||||
settings.transfer_owner=Jaunais īpašnieks
|
||||
settings.make_transfer=Mainīt
|
||||
@@ -598,9 +608,9 @@ settings.hooks_desc=Tīmekļa āķi ļauj paziņot ārējiem servisiem par notei
|
||||
settings.webhook_deletion=Dzēst tīmekļa āķi
|
||||
settings.webhook_deletion_desc=Dzēšot tīmekļa āķi tiks dzēsta visa ar to saistītā informācija un izpildes vēsture. Vai vēlaties turpināt?
|
||||
settings.webhook_deletion_success=Tīmekļa āķis tika veiksmīgi izdzēsts!
|
||||
settings.webhook.test_delivery=Test Delivery
|
||||
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.test_delivery=Testa piegāde
|
||||
settings.webhook.test_delivery_desc=Veikt viltus push-notikuma piegādi lai notestētu Jūsu tīmekļa āķa iestatījumus
|
||||
settings.webhook.test_delivery_success=Testa web-āķis ir pievienots piegādes rindai. Var paiet dažas sekundes, kamēr tas parādīsies piegāžu vēsturē.
|
||||
settings.webhook.request=Pieprasījums
|
||||
settings.webhook.response=Atbilde
|
||||
settings.webhook.headers=Galvenes
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name=Autentifikācijas pieteikšanās vārds
|
||||
users.password_helper=Atstājiet tukšu, ja nevēlaties mainīt.
|
||||
users.update_profile_success=Konta profils tika veiksmīgi saglabāts.
|
||||
users.edit_account=Labot kontu
|
||||
users.max_repo_creation=Maksimāls repozitoriju veidošanas limits
|
||||
users.max_repo_creation_desc=(Uzlikt -1 lai izmantotu globālu limitu pēc noklusējuma)
|
||||
users.is_activated=Konts ir aktivizēts
|
||||
users.is_admin=Šim kontam ir administratora piekļuves tiesības
|
||||
users.allow_git_hook=Šim kontam ir tiesības pievienot/labot Git āķus
|
||||
@@ -995,18 +1007,18 @@ monitor.start=Sākuma laiks
|
||||
monitor.execute_time=Izpildes laiks
|
||||
|
||||
notices.system_notice_list=Sistēmas paziņojumi
|
||||
notices.view_detail_header=View Notice Detail
|
||||
notices.actions=Actions
|
||||
notices.select_all=Select All
|
||||
notices.deselect_all=Deselect All
|
||||
notices.inverse_selection=Inverse Selection
|
||||
notices.delete_selected=Delete Selected
|
||||
notices.delete_all=Delete All Notices
|
||||
notices.view_detail_header=Skatīt paziņojuma detaļas
|
||||
notices.actions=Darbības
|
||||
notices.select_all=Iezīmēt visu
|
||||
notices.deselect_all=Atcelt visa iezīmēšanu
|
||||
notices.inverse_selection=Apgriezeniskā iezīmēšana
|
||||
notices.delete_selected=Dzēst iezīmēto
|
||||
notices.delete_all=Dzēst visus paziņojumus
|
||||
notices.type=Veids
|
||||
notices.type_1=Repozitorijs
|
||||
notices.desc=Apraksts
|
||||
notices.op=Op.
|
||||
notices.delete_success=System notices have been deleted successfully.
|
||||
notices.delete_success=Sistēmas paziņojumi tika veiksmīgi izdzēstas.
|
||||
|
||||
[action]
|
||||
create_repo=izveidoja repozitoriju <a href="%s">%s</a>
|
||||
@@ -1018,7 +1030,7 @@ comment_issue=`pievienoja komentāru problēmai <a href="%s/issues/%s">%s#%[2]s<
|
||||
merge_pull_request=`sapludināja izmaiņu pieprasījumu <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="%s">%s</a>
|
||||
push_tag=pievienoja tagu <a href="%s/src/%s">%[2]s</a> repozitorijam <a href="%[1]s">%[3]s</a>
|
||||
compare_2_commits=Veikt salīdzināšanu starp šīm 2 revīzijām
|
||||
compare_commits=Salīdzināt šīs %d revīzijas
|
||||
|
||||
[tool]
|
||||
ago=atpakaļ
|
||||
|
||||
@@ -28,6 +28,7 @@ organization=Organisatie
|
||||
mirror=Spiegel
|
||||
new_repo=Nieuwe repositorie
|
||||
new_migrate=Nieuwe migratie
|
||||
new_mirror=New Mirror
|
||||
new_fork=Nieuwe vork Repository
|
||||
new_org=Nieuwe organisatie
|
||||
manage_org=Beheer organisaties
|
||||
@@ -247,6 +248,7 @@ uid=uid
|
||||
|
||||
public_profile=Openbaar profiel
|
||||
profile_desc=Uw e-mailadres is openbaar en zal gebruikt worden voor alle account gerelateerde berichtgevingen en bewerkingingen die via de website worden gedaan.
|
||||
password_username_disabled=Non-local type users are not allowed to change their username.
|
||||
full_name=Volledige naam
|
||||
website=Website
|
||||
location=Locatie
|
||||
@@ -271,6 +273,7 @@ new_password=Nieuw wachtwoord
|
||||
retype_new_password=Retype New Password
|
||||
password_incorrect=Huidig wachtwoord is niet correct.
|
||||
change_password_success=Wachtwoord is succesvol gewijzigd. U kunt nu met uw nieuwe wachtwoord inloggen.
|
||||
password_change_disabled=Non-local type users are not allowed to change their password.
|
||||
|
||||
emails=E-mailadressen
|
||||
manage_emails=E-mailadressen beheren
|
||||
@@ -352,10 +355,13 @@ auto_init=Initialiseer deze repositorie met de geselecteerde bestanden en sjablo
|
||||
create_repo=Nieuwe Repositorie
|
||||
default_branch=Standaard branch
|
||||
mirror_interval=Mirror interval(uur)
|
||||
mirror_address=Mirror Address
|
||||
mirror_address_desc=Please include necessary user credentials in the address.
|
||||
watchers=Watchers
|
||||
stargazers=Stargazers
|
||||
forks=Forks
|
||||
|
||||
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
|
||||
form.name_reserved=Repositorienaam '%s' is gereserveerd.
|
||||
form.name_pattern_not_allowed=Repositorie naampatroon '%s' is niet toegestaan.
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied=You are not allowed to import local repositories.
|
||||
migrate.invalid_local_path=Ongeldig lokaal pad, het pad bestaat niet of het is geen map.
|
||||
migrate.failed=Migration failed: %v
|
||||
|
||||
mirror_from=mirror from
|
||||
forked_from=geforked van
|
||||
fork_from_self=U kunt geen repository forken die u al beheert!
|
||||
copy_link=Kopieer
|
||||
@@ -506,9 +513,9 @@ pulls.merged=Merged
|
||||
pulls.has_merged=This pull request has been merged successfully!
|
||||
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
|
||||
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
|
||||
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request.
|
||||
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits.
|
||||
pulls.cannot_auto_merge_helper=Please use command line tool to solve it.
|
||||
pulls.can_auto_merge_desc=This pull request can be merged automatically.
|
||||
pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
|
||||
pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
|
||||
pulls.merge_pull_request=Samenvoegen van pull verzoek
|
||||
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
|
||||
|
||||
@@ -563,6 +570,9 @@ settings.update_settings=Instellingen bewerken
|
||||
settings.change_reponame_prompt=This change will affect how links relate to the repository.
|
||||
settings.advanced_settings=Advanced Settings
|
||||
settings.wiki_desc=Enable wiki to allow people write documents
|
||||
settings.use_external_wiki=Use external wiki
|
||||
settings.external_wiki_url=External Wiki URL
|
||||
settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
|
||||
settings.issues_desc=Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Use external issue tracker
|
||||
settings.tracker_url_format=External Issue Tracker URL Format
|
||||
@@ -600,7 +610,7 @@ settings.webhook_deletion_desc=Delete this webhook will remove its information a
|
||||
settings.webhook_deletion_success=Webhook has been deleted successfully!
|
||||
settings.webhook.test_delivery=Test Delivery
|
||||
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may take few seconds before it shows up in the delivery history.
|
||||
settings.webhook.request=Verzoek
|
||||
settings.webhook.response=Antwoord
|
||||
settings.webhook.headers=Headers
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name=Authentication Login Name
|
||||
users.password_helper=Leave it empty to remain unchanged.
|
||||
users.update_profile_success=Profiel is succesvol bijgewerkt.
|
||||
users.edit_account=Bewerk account
|
||||
users.max_repo_creation=Maximum Repository Creation Limit
|
||||
users.max_repo_creation_desc=(Set -1 to use global default limit)
|
||||
users.is_activated=Dit account is geactiveerd
|
||||
users.is_admin=Dit account heeft beheerdersrechten
|
||||
users.allow_git_hook=Deze account beschikt over machtigingen voor het maken van Git haken
|
||||
@@ -1018,7 +1030,7 @@ comment_issue=`reactie op issue <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo=repositorie verplaatst naar <code>%s</code> naar <a href="%s">%s</a>
|
||||
push_tag=geduwd label <a href="%s/src/%s"> %[2]s</a> naar <a href="%[1]s"> %[3]s</a>
|
||||
compare_2_commits=Weergave vergelijking voor deze 2 commits
|
||||
compare_commits=View comparison for these %d commits
|
||||
|
||||
[tool]
|
||||
ago=geleden
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,7 @@ organization=Organização
|
||||
mirror=Espelho
|
||||
new_repo=Novo Repositório
|
||||
new_migrate=Nova Migração
|
||||
new_mirror=Novo espelho
|
||||
new_fork=Novo Fork de Repositório
|
||||
new_org=Nova Organização
|
||||
manage_org=Gerenciar Organizações
|
||||
@@ -38,7 +39,7 @@ your_profile=Seu perfil
|
||||
your_settings=Suas configurações
|
||||
|
||||
news_feed=Feed de Notícias
|
||||
pull_requests=Solicitações de Pull
|
||||
pull_requests=Pull Requests
|
||||
issues=Problemas
|
||||
|
||||
cancel=Cancelar
|
||||
@@ -247,6 +248,7 @@ 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.
|
||||
password_username_disabled=Usuários do tipo não-local não são permitidos de mudarem seu nome de usuário.
|
||||
full_name=Nome Completo
|
||||
website=Site
|
||||
location=Localização
|
||||
@@ -271,6 +273,7 @@ new_password=Nova Senha
|
||||
retype_new_password=Digite novamente a 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.
|
||||
password_change_disabled=Usuários do tipo não-local não são permitidos de mudarem sua senha.
|
||||
|
||||
emails=Endereços de E-mail
|
||||
manage_emails=Gerenciar endereços de e-mail
|
||||
@@ -352,10 +355,13 @@ auto_init=Inicializar este repositório com os arquivos selecionados e modelo
|
||||
create_repo=Criar Repositório
|
||||
default_branch=Branch padrão
|
||||
mirror_interval=Intervalo de Espelho (hora)
|
||||
mirror_address=Endereço do espelho
|
||||
mirror_address_desc=Por favor, inclua as credenciais do usuário necessários no endereço.
|
||||
watchers=Observadores
|
||||
stargazers=Usuários que estrelaram
|
||||
forks=Forks
|
||||
|
||||
form.reach_limit_of_creation=O proprietário atingiu o limite máximo de criação de repositórios de %d.
|
||||
form.name_reserved=O nome de repositório '%s' não pode ser usado.
|
||||
form.name_pattern_not_allowed=Não é permitido usar o padrão '%s' para o nome de repositório.
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied=Você não pode importar repositórios locais.
|
||||
migrate.invalid_local_path=Caminho local inválido, não existe ou não é um diretório.
|
||||
migrate.failed=Migração falhou: %v
|
||||
|
||||
mirror_from=espelho de
|
||||
forked_from=forkado de
|
||||
fork_from_self=Você não pode criar fork de um repositório que já é seu!
|
||||
copy_link=Copiar
|
||||
@@ -388,7 +395,7 @@ create_new_repo_command=Criar um novo repositório na linha de comando
|
||||
push_exist_repo=Push um repositório existente na linha de comando
|
||||
repo_is_empty=Este repositório está vazio, por favor volte mais tarde!
|
||||
|
||||
code=Code
|
||||
code=Código
|
||||
branch=Branch
|
||||
tree=Árvore
|
||||
filter_branch_and_tag=Filtrar branch ou tag
|
||||
@@ -506,9 +513,9 @@ pulls.merged=Merge realizado
|
||||
pulls.has_merged=Este pull request foi mesclado com sucesso!
|
||||
pulls.data_broken=Dados deste pull request foram quebrados devido à deleção de informação do fork.
|
||||
pulls.is_checking=A verificação do conflito ainda está em progresso, por favor recarregue a página em instantes.
|
||||
pulls.can_auto_merge_desc=Você pode realizar uma auto-mescla neste pull request.
|
||||
pulls.cannot_auto_merge_desc=Você não pode realizar uma auto-mescla porque há conflitos entre os commits.
|
||||
pulls.cannot_auto_merge_helper=Por favor, utilize linha de comando para solucionar isto.
|
||||
pulls.can_auto_merge_desc=Este pull request foi mesclado automaticamente.
|
||||
pulls.cannot_auto_merge_desc=Este pull request não pode ser mesclado automaticamente pois há conflitos.
|
||||
pulls.cannot_auto_merge_helper=Por favor, mescle manualmente para resolver os conflitos.
|
||||
pulls.merge_pull_request=Merge Pull Request
|
||||
pulls.open_unmerged_pull_exists=' Você não pode executar a operação de reabrir porque já existe uma solicitação de pull aberta (#%d) do mesmo repositório com as mesmas informações de merge e está esperando pelo merge.'
|
||||
|
||||
@@ -537,20 +544,20 @@ milestones.deletion_desc=Excluir este marco removerá a informação dele em tod
|
||||
milestones.deletion_success=Marco excluído com sucesso!
|
||||
|
||||
wiki=Wiki
|
||||
wiki.welcome=Welcome to Wiki!
|
||||
wiki.welcome_desc=Wiki is the place where you would like to document your project together and make it better.
|
||||
wiki.create_first_page=Create the first page
|
||||
wiki.page=Page
|
||||
wiki.filter_page=Filter page
|
||||
wiki.new_page=Create New Page
|
||||
wiki.default_commit_message=Write a note about this update (optional).
|
||||
wiki.save_page=Save Page
|
||||
wiki.last_commit_info=%s edited this page %s
|
||||
wiki.edit_page_button=Edit
|
||||
wiki.new_page_button=New Page
|
||||
wiki.page_already_exists=Wiki page with same name already exists.
|
||||
wiki.pages=Pages
|
||||
wiki.last_updated=Last updated %s
|
||||
wiki.welcome=Bem-vindo ao wiki!
|
||||
wiki.welcome_desc=Wiki é o lugar onde você gostaria de documentar o seu projeto em conjunto e torná-lo melhor.
|
||||
wiki.create_first_page=Criar a primeira página
|
||||
wiki.page=Página
|
||||
wiki.filter_page=Filtrar página
|
||||
wiki.new_page=Criar nova página
|
||||
wiki.default_commit_message=Escrever um comentário sobre esta atualização (opcional).
|
||||
wiki.save_page=Salvar página
|
||||
wiki.last_commit_info=%s editou esta página %s
|
||||
wiki.edit_page_button=Editar
|
||||
wiki.new_page_button=Nova página
|
||||
wiki.page_already_exists=já existe uma página de wiki com o mesmo nome.
|
||||
wiki.pages=Páginas
|
||||
wiki.last_updated=Última atualização %s
|
||||
|
||||
settings=Configurações
|
||||
settings.options=Opções
|
||||
@@ -561,13 +568,16 @@ settings.basic_settings=Configurações Básicas
|
||||
settings.site=Site Oficial
|
||||
settings.update_settings=Configurações de Atualização
|
||||
settings.change_reponame_prompt=Este mudanças vai afetar os links para este repositório.
|
||||
settings.advanced_settings=Advanced Settings
|
||||
settings.wiki_desc=Enable wiki to allow people write documents
|
||||
settings.issues_desc=Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Use external issue tracker
|
||||
settings.tracker_url_format=External Issue Tracker URL Format
|
||||
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc=Enable pull requests to accept public contributions
|
||||
settings.advanced_settings=Configurações avançadas
|
||||
settings.wiki_desc=Habilitar o wiki para permitir que as pessoas escrevam documentos
|
||||
settings.use_external_wiki=Usar wiki externa
|
||||
settings.external_wiki_url=URL externa da wiki
|
||||
settings.external_wiki_url_desc=Os visitantes serão redirecionados para a URL quando clicarem na aba.
|
||||
settings.issues_desc=Habilitar gerenciamento de "problemas" nativo
|
||||
settings.use_external_issue_tracker=Usar issue tracker externo
|
||||
settings.tracker_url_format=Formato de URL do issue tracker externo
|
||||
settings.tracker_url_format_desc=Você pode usar o espaço reservado <code>{user} {repo} {index}</code> para o nome do usuário, índice de nome e a questão do repositório.
|
||||
settings.pulls_desc=Habilitar pull requests para aceitar contribuições públicas
|
||||
settings.danger_zone=Zona de Perigo
|
||||
settings.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.
|
||||
@@ -582,7 +592,7 @@ settings.delete_notices_2=- Esta operação irá apagar permanentemente o tudo d
|
||||
settings.delete_notices_fork_1=- Se este repositório é público, todos os forks se tornarão independentes após a deleção.
|
||||
settings.delete_notices_fork_2=- Se este repositório é privado, todos os forks serão removidos imediatamente.
|
||||
settings.delete_notices_fork_3=- Se você deseja manter todos os forks, por favor muda a visibilidade do repositório para pública primeiro.
|
||||
settings.deletion_success=Repository has been deleted successfully!
|
||||
settings.deletion_success=Repositório excluído com sucesso!
|
||||
settings.update_settings_success=As opções do repositório foram atualizadas com sucesso.
|
||||
settings.transfer_owner=Novo Dono
|
||||
settings.make_transfer=Fazer Transferência
|
||||
@@ -598,9 +608,9 @@ settings.hooks_desc=Hooks da web ou Webhooks permitem serviços externos serem n
|
||||
settings.webhook_deletion=Deletar Webhook
|
||||
settings.webhook_deletion_desc=Deletar este Webhook vai remover sua informação e todo o histórico de entrega. Deseja continuar?
|
||||
settings.webhook_deletion_success=Webhook deletado com sucesso!
|
||||
settings.webhook.test_delivery=Test Delivery
|
||||
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.test_delivery=Entrega de teste
|
||||
settings.webhook.test_delivery_desc=Enviar uma entrega de evento de push falso para testar suas configurações de webhook
|
||||
settings.webhook.test_delivery_success=O teste webhook foi adicionado para a fila de entrega. Pode demorar alguns segundos antes de ser exibido no histórico de entrega.
|
||||
settings.webhook.request=Solicitação
|
||||
settings.webhook.response=Resposta
|
||||
settings.webhook.headers=Cabeçalhos
|
||||
@@ -640,7 +650,7 @@ settings.slack_domain=Domínio
|
||||
settings.slack_channel=Canal
|
||||
settings.deploy_keys=Chaves de Deploy
|
||||
settings.add_deploy_key=Nova chave
|
||||
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys.
|
||||
settings.deploy_key_desc=Chave de deploy só tem acesso somente leitura. Não é igual as chaves SSH de conta pessoal.
|
||||
settings.no_deploy_keys=Você ainda não adicionou chaves para implantação de software.
|
||||
settings.title=Título
|
||||
settings.deploy_key_content=Conteúdo da chave
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name=Nome de login da autenticação
|
||||
users.password_helper=Deixe em branco para não mudar.
|
||||
users.update_profile_success=O perfil da conta foi atualizado com sucesso.
|
||||
users.edit_account=Editar Conta
|
||||
users.max_repo_creation=Limite máximo de criação de repositórios
|
||||
users.max_repo_creation_desc=(Use "-1" para utilizar o limite padrão)
|
||||
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 hooks do Git
|
||||
@@ -890,8 +902,8 @@ auths.bind_password=Vincular senha
|
||||
auths.bind_password_helper=Atenção: Esta senha é armazenada em texto plano. Não use uma conta com muitos privilégios.
|
||||
auths.user_base=Base de pesquisa do usuário
|
||||
auths.user_dn=Usuário do DN
|
||||
auths.attribute_username=Username attribute
|
||||
auths.attribute_username_placeholder=Leave empty to use sign-in form field value for user name.
|
||||
auths.attribute_username=Atributo nome de usuário
|
||||
auths.attribute_username_placeholder=Deixe vazio para usar o valor do campo de formulário de entrada de nome de usuário.
|
||||
auths.attribute_name=Atributo primeiro nome
|
||||
auths.attribute_surname=Atributo sobrenome
|
||||
auths.attribute_mail=Atributo e-mail
|
||||
@@ -995,18 +1007,18 @@ monitor.start=Hora de Início
|
||||
monitor.execute_time=Tempo de Execução
|
||||
|
||||
notices.system_notice_list=Sistema de Notificações
|
||||
notices.view_detail_header=View Notice Detail
|
||||
notices.actions=Actions
|
||||
notices.select_all=Select All
|
||||
notices.deselect_all=Deselect All
|
||||
notices.inverse_selection=Inverse Selection
|
||||
notices.delete_selected=Delete Selected
|
||||
notices.delete_all=Delete All Notices
|
||||
notices.view_detail_header=Ver detalhe do anúncio
|
||||
notices.actions=Ações
|
||||
notices.select_all=Selecionar tudo
|
||||
notices.deselect_all=Desmarcar tudo
|
||||
notices.inverse_selection=Seleção inversa
|
||||
notices.delete_selected=Apagar seleção
|
||||
notices.delete_all=Excluir todos os avisos
|
||||
notices.type=Tipo
|
||||
notices.type_1=Repositório
|
||||
notices.desc=Descrição
|
||||
notices.op=Op.
|
||||
notices.delete_success=System notices have been deleted successfully.
|
||||
notices.delete_success=Avisos do sistema foram excluídos com sucesso.
|
||||
|
||||
[action]
|
||||
create_repo=repositório criado <a href="%s"> %s</a>
|
||||
@@ -1018,7 +1030,7 @@ comment_issue='comentou sobre a questão <a href="%s/issues/%s">%s#%[2]s</a>'
|
||||
merge_pull_request=`mesclou o pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
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
|
||||
compare_commits=Ver comparação entre esses %d commits
|
||||
|
||||
[tool]
|
||||
ago=atrás
|
||||
|
||||
@@ -28,6 +28,7 @@ organization=Организация
|
||||
mirror=Зеркало
|
||||
new_repo=Новый репозиторий
|
||||
new_migrate=Новая Миграция
|
||||
new_mirror=Новое зеркало
|
||||
new_fork=Новый проект из репозитория
|
||||
new_org=Новая Организация
|
||||
manage_org=Управление Организацией
|
||||
@@ -38,7 +39,7 @@ your_profile=Ваш профиль
|
||||
your_settings=Ваши настройки
|
||||
|
||||
news_feed=Лента новостей
|
||||
pull_requests=Pull Requests
|
||||
pull_requests=Запросы на слияние
|
||||
issues=Вопросы
|
||||
|
||||
cancel=Отмена
|
||||
@@ -247,6 +248,7 @@ uid=UID
|
||||
|
||||
public_profile=Открытый профиль
|
||||
profile_desc=Адрес вашей электронной почты является публичным и будет использован для любых уведомлений, связанных с аккаунтом, а также для любых действий, совершенных через сайт.
|
||||
password_username_disabled=Нелокальные пользователи не могут изменить своё имя.
|
||||
full_name=ФИО
|
||||
website=Веб-сайт
|
||||
location=Местоположение
|
||||
@@ -271,6 +273,7 @@ new_password=Новый пароль
|
||||
retype_new_password=Подтверждение нового пароля
|
||||
password_incorrect=Текущий пароль не правильный.
|
||||
change_password_success=Пароль сменен успешно. Теперь вы можете войти с новым паролем.
|
||||
password_change_disabled=Нелокальные пользователи не могут изменить свой пароль.
|
||||
|
||||
emails=Адреса электронной почты
|
||||
manage_emails=Управление адресами электронной почты
|
||||
@@ -352,10 +355,13 @@ auto_init=Инициализировать этот репозиторий вы
|
||||
create_repo=Создать репозиторий
|
||||
default_branch=Ветка по умолчанию
|
||||
mirror_interval=Интервал зеркалирования (час)
|
||||
mirror_address=Адрес зеркала
|
||||
mirror_address_desc=Укажите необходимые учетные данные в адрес.
|
||||
watchers=Наблюдатели
|
||||
stargazers=Звездочеты
|
||||
forks=Форки
|
||||
|
||||
form.reach_limit_of_creation=У владельца достигнут максимальный предел в %d создаваемых репозиториев.
|
||||
form.name_reserved=Имя репозитория '%s' зарезервировано.
|
||||
form.name_pattern_not_allowed=Шаблон имени репозитория '%s' не допускается.
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied=У вас нет прав на импорт локал
|
||||
migrate.invalid_local_path=Недопустимый локальный путь. Возможно он не существует или является не папкой.
|
||||
migrate.failed=Миграция не удалась: %v
|
||||
|
||||
mirror_from=зеркало из
|
||||
forked_from=форк от
|
||||
fork_from_self=Вы не можете форкнуть репозитарий, так как Вы уже его владелец!
|
||||
copy_link=Скопировать
|
||||
@@ -388,7 +395,7 @@ create_new_repo_command=Создать новый репозиторий из к
|
||||
push_exist_repo=Отправить существующий репозиторий из командной строки
|
||||
repo_is_empty=Этот репозиторий пуст, пожалуйста, возвращайтесь позже!
|
||||
|
||||
code=Code
|
||||
code=Код
|
||||
branch=Ветка
|
||||
tree=Дерево
|
||||
filter_branch_and_tag=Фильтр по ветке или тегу
|
||||
@@ -450,7 +457,7 @@ issues.filter_sort.recentupdate=Недавно обновленные
|
||||
issues.filter_sort.leastupdate=Давно обновленные
|
||||
issues.filter_sort.mostcomment=Большего комментариев
|
||||
issues.filter_sort.leastcomment=Меньше комментариев
|
||||
issues.opened_by=%[1] открыта <a href="%[2]s">%[3]s</a>
|
||||
issues.opened_by=%[1]s открыта <a href="%[2]s">%[3]s</a>
|
||||
issues.opened_by_fake=%[1]s открыта %[2]s
|
||||
issues.previous=Предыдущая страница
|
||||
issues.next=Следующая страница
|
||||
@@ -501,14 +508,14 @@ pulls.merged_title_desc=слито %[1]d коммит(ов) из <code>%[2]s</co
|
||||
pulls.tab_conversation=Обсуждение
|
||||
pulls.tab_commits=Коммиты
|
||||
pulls.tab_files=Измененные файлы
|
||||
pulls.reopen_to_merge=Пожалуйста пересоздайте пулл-реквест для слияния.
|
||||
pulls.reopen_to_merge=Пожалуйста снова откройте этот запрос для слияния.
|
||||
pulls.merged=Слито
|
||||
pulls.has_merged=Слияние этого пулл-реквеста успешно завершено!
|
||||
pulls.data_broken=Содержимое этого пулл-реквеста было нарушено, вследствии удаления или клонирования информации.
|
||||
pulls.is_checking=Продолжается проверка конфликтов, пожалуйста обновите страницу несколько позже.
|
||||
pulls.can_auto_merge_desc=Вы можете провести операцию автоматического слияния для этого пулл-реквеста.
|
||||
pulls.cannot_auto_merge_desc=Вы не можете произвести операцию автоматического слияния, потому как существуют конфликты между коммитами.
|
||||
pulls.cannot_auto_merge_helper=Используйте командную строку для решения этого.
|
||||
pulls.can_auto_merge_desc=Этот запрос на слияние может быть объединён автоматически.
|
||||
pulls.cannot_auto_merge_desc=Этот запрос на слияние не может быть объединён автоматически.
|
||||
pulls.cannot_auto_merge_helper=Пожалуйста, совершите слияние вручную для урегулирования конфликтов.
|
||||
pulls.merge_pull_request=Слить пулл-реквест
|
||||
pulls.open_unmerged_pull_exists=`Вы не можете произвести операцию переоткрытия, потому что уже существует пулл-реквест (#%d) из этого же репозитория, с такими же параметрами слияния, который ожидает слияния.`
|
||||
|
||||
@@ -536,21 +543,21 @@ milestones.deletion=Удаление контрольной точки
|
||||
milestones.deletion_desc=Удаление этой контрольной точки приведет с удалению всей информации, во всех вопросах (Issues). Вы действительно хотите продолжить?
|
||||
milestones.deletion_success=Контрольная точка успешно удалена!
|
||||
|
||||
wiki=Wiki
|
||||
wiki.welcome=Welcome to Wiki!
|
||||
wiki.welcome_desc=Wiki is the place where you would like to document your project together and make it better.
|
||||
wiki.create_first_page=Create the first page
|
||||
wiki.page=Page
|
||||
wiki.filter_page=Filter page
|
||||
wiki.new_page=Create New Page
|
||||
wiki.default_commit_message=Write a note about this update (optional).
|
||||
wiki.save_page=Save Page
|
||||
wiki.last_commit_info=%s edited this page %s
|
||||
wiki.edit_page_button=Edit
|
||||
wiki.new_page_button=New Page
|
||||
wiki.page_already_exists=Wiki page with same name already exists.
|
||||
wiki.pages=Pages
|
||||
wiki.last_updated=Last updated %s
|
||||
wiki=Вики
|
||||
wiki.welcome=Добро пожаловать в Вики!
|
||||
wiki.welcome_desc=Вики это место, где вы хотели бы документировать проект вместе и сделать его лучше.
|
||||
wiki.create_first_page=Создать первую страницу
|
||||
wiki.page=Страница
|
||||
wiki.filter_page=Фильтр страницы
|
||||
wiki.new_page=Создать новую страницу
|
||||
wiki.default_commit_message=Написать заметку о данном обновлении (опционально).
|
||||
wiki.save_page=Сохранить страницу
|
||||
wiki.last_commit_info=%s редактировал эту страницу %s
|
||||
wiki.edit_page_button=Редактировать
|
||||
wiki.new_page_button=Новая страница
|
||||
wiki.page_already_exists=Вики-страница с таким именем уже существует.
|
||||
wiki.pages=Страницы
|
||||
wiki.last_updated=Последнее обновление %s
|
||||
|
||||
settings=Настройки
|
||||
settings.options=Опции
|
||||
@@ -561,13 +568,16 @@ settings.basic_settings=Основные параметры
|
||||
settings.site=Официальный сайт
|
||||
settings.update_settings=Обновить настройки
|
||||
settings.change_reponame_prompt=Это изменение повлияет на отношения ссылок к этому репозиторию.
|
||||
settings.advanced_settings=Advanced Settings
|
||||
settings.wiki_desc=Enable wiki to allow people write documents
|
||||
settings.issues_desc=Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Use external issue tracker
|
||||
settings.tracker_url_format=External Issue Tracker URL Format
|
||||
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc=Enable pull requests to accept public contributions
|
||||
settings.advanced_settings=Расширенные настройки
|
||||
settings.wiki_desc=Включить Вики, чтобы позволить людям ипсать документы
|
||||
settings.use_external_wiki=Использовать внешнюю Wiki
|
||||
settings.external_wiki_url=URL-адрес внешней вики
|
||||
settings.external_wiki_url_desc=Посетители будут перенаправлены на URL-адрес, когда они кликнут по вкладке.
|
||||
settings.issues_desc=Включить встроенную, легковесную систему отслеживания ошибок
|
||||
settings.use_external_issue_tracker=Использовать внешнюю систему отслеживания ошибок
|
||||
settings.tracker_url_format=Внешний формат ссылки системы отслеживания ошибок.
|
||||
settings.tracker_url_format_desc=Вы можете использовать шаблон <code>{user} {repo} {index}</code> для имени пользователя, репозитория и номера обсуждения.
|
||||
settings.pulls_desc=Включить публичные пулл-реквесты
|
||||
settings.danger_zone=Опасная зона
|
||||
settings.transfer=Передать права собственности
|
||||
settings.transfer_desc=Передать репозиторий другому пользователю или организации где у вас есть права администратора.
|
||||
@@ -582,7 +592,7 @@ settings.delete_notices_2=- Эта операция перманентно уд
|
||||
settings.delete_notices_fork_1=- Если данный репозиторий является публичным, все склонированные репозитории останутся независимыми, после его удаления.
|
||||
settings.delete_notices_fork_2=- Если данный репозиторий является приватным, все его форки будут удалены вместе с ним.
|
||||
settings.delete_notices_fork_3=- Если вы хотите сохранить все форки после удаления репозитория, то сначала сделайте его публичным.
|
||||
settings.deletion_success=Repository has been deleted successfully!
|
||||
settings.deletion_success=Репозиторий был успешно удалён!
|
||||
settings.update_settings_success=Настройка репозитория обновлена успешно.
|
||||
settings.transfer_owner=Новый владелец
|
||||
settings.make_transfer=Выполнить передачу
|
||||
@@ -598,9 +608,9 @@ settings.hooks_desc=Webhooks позволяют внешним службам п
|
||||
settings.webhook_deletion=Удалить веб-хук
|
||||
settings.webhook_deletion_desc=Удаление этого веб-хука приведет к удалению всей, связанной с ним, информации, включая историю. Хотите продолжить?
|
||||
settings.webhook_deletion_success=Веб-хук успешно удален!
|
||||
settings.webhook.test_delivery=Test Delivery
|
||||
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.test_delivery=Проверить доставку
|
||||
settings.webhook.test_delivery_desc=Отправить push для тестирования настройки веб-хуков
|
||||
settings.webhook.test_delivery_success=Тест веб-хука была добавлен в очередь доставки. Это может занять несколько секунд, прежде чем он отобразится в истории доставки.
|
||||
settings.webhook.request=Запрос
|
||||
settings.webhook.response=Ответ
|
||||
settings.webhook.headers=Заголовки
|
||||
@@ -640,7 +650,7 @@ settings.slack_domain=Домен
|
||||
settings.slack_channel=Канал
|
||||
settings.deploy_keys=Ключи развертывания
|
||||
settings.add_deploy_key=Добавить ключ развертывания
|
||||
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys.
|
||||
settings.deploy_key_desc=Ключи развёртывания доступны только для чтения. Это не то же самое что и SSH-ключи аккаунта.
|
||||
settings.no_deploy_keys=Вы не добавляли ключи развертывания.
|
||||
settings.title=Заголовок
|
||||
settings.deploy_key_content=Содержимое
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name=Логин для авторизации
|
||||
users.password_helper=Оставьте пустым, чтобы оставить без изменений.
|
||||
users.update_profile_success=Профиль учетной записи обновлен успешно.
|
||||
users.edit_account=Изменение учетной записи
|
||||
users.max_repo_creation=Ограничение максимального количества создаваемых репозиториев
|
||||
users.max_repo_creation_desc=(Установить -1 для использования стандартного глобального значения предела)
|
||||
users.is_activated=Эта учетная запись активирована
|
||||
users.is_admin=У этой учетной записи есть права администратора
|
||||
users.allow_git_hook=Пользователь имеет право создать Git перехватчик
|
||||
@@ -890,8 +902,8 @@ auths.bind_password=Привязать пароль
|
||||
auths.bind_password_helper=Внимание: Этот пароль сохранен в небезопасном виде. Не используйте высоко-привилегированную учетную запись.
|
||||
auths.user_base=База для поиска пользователя
|
||||
auths.user_dn=DN пользователя
|
||||
auths.attribute_username=Username attribute
|
||||
auths.attribute_username_placeholder=Leave empty to use sign-in form field value for user name.
|
||||
auths.attribute_username=Атрибут username
|
||||
auths.attribute_username_placeholder=Оставьте пустым, чтобы использовать имя пользователя для регистрации.
|
||||
auths.attribute_name=Имя аттрибута
|
||||
auths.attribute_surname=Фамилия аттрибута
|
||||
auths.attribute_mail=Электронная почта аттрибута
|
||||
@@ -995,21 +1007,21 @@ monitor.start=Момент начала
|
||||
monitor.execute_time=Время выполнения
|
||||
|
||||
notices.system_notice_list=Система уведомлений
|
||||
notices.view_detail_header=View Notice Detail
|
||||
notices.actions=Actions
|
||||
notices.select_all=Select All
|
||||
notices.deselect_all=Deselect All
|
||||
notices.inverse_selection=Inverse Selection
|
||||
notices.delete_selected=Delete Selected
|
||||
notices.delete_all=Delete All Notices
|
||||
notices.view_detail_header=Подробности уведомления
|
||||
notices.actions=Действия
|
||||
notices.select_all=Выбрать всё
|
||||
notices.deselect_all=Убрать выделение со всего
|
||||
notices.inverse_selection=Инверсия выделения
|
||||
notices.delete_selected=Удалить выбранные
|
||||
notices.delete_all=Удалить все уведомления
|
||||
notices.type=Тип
|
||||
notices.type_1=Репозиторий
|
||||
notices.desc=Описание
|
||||
notices.op=Op.
|
||||
notices.delete_success=System notices have been deleted successfully.
|
||||
notices.delete_success=Системное уведомление успешно удалено.
|
||||
|
||||
[action]
|
||||
create_repo=создан репозиторий <a href="%s"> %s</a>
|
||||
create_repo=создал репозиторий <a href="%s"> %s</a>
|
||||
rename_repo=репозиторий переименован из <code>%[1]s</code>на <a href="%[2]s">%[3]s</a>
|
||||
commit_repo=запушил <a href="%[1]s/src/%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a>
|
||||
create_issue=`открытый вопрос <a href="%s/issues/%s">%s#%[2]</a>`
|
||||
@@ -1018,7 +1030,7 @@ comment_issue=`прокомментировал(а) вопрос <a href="%s/iss
|
||||
merge_pull_request=`слил пул реквест <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo=перенес репозиторий <code>%s</code> в <a href="%s">%s</a>
|
||||
push_tag=запушил тэг <a href="%s/src/%s">%[2]s</a> в <a href="%[1]s">%[3]s</a>
|
||||
compare_2_commits=Просмотреть сравнение двух коммитов
|
||||
compare_commits=Просмотр сравнение для этих %d коммитов
|
||||
|
||||
[tool]
|
||||
ago=назад
|
||||
|
||||
@@ -28,6 +28,7 @@ organization=组织
|
||||
mirror=镜像
|
||||
new_repo=创建新的仓库
|
||||
new_migrate=迁移外部仓库
|
||||
new_mirror=创建新的镜像
|
||||
new_fork=创建新的派生仓库
|
||||
new_org=创建新的组织
|
||||
manage_org=管理我的组织
|
||||
@@ -247,6 +248,7 @@ uid=用户 ID
|
||||
|
||||
public_profile=公开信息
|
||||
profile_desc=您的邮箱地址将会被公开,并被用于接收帐户的所有提醒和通知。
|
||||
password_username_disabled=非本地类型的用户被禁止修改用户名。
|
||||
full_name=自定义名称
|
||||
website=个人网站
|
||||
location=所在地区
|
||||
@@ -271,6 +273,7 @@ new_password=新的密码
|
||||
retype_new_password=重新输入新的密码
|
||||
password_incorrect=当前密码不正确!
|
||||
change_password_success=密码修改成功!您现在可以使用新的密码登录。
|
||||
password_change_disabled=非本地类型的用户被禁止修改密码。
|
||||
|
||||
emails=邮箱地址
|
||||
manage_emails=管理邮箱地址
|
||||
@@ -352,10 +355,13 @@ auto_init=使用选定的文件和模板初始化仓库
|
||||
create_repo=创建仓库
|
||||
default_branch=默认分支
|
||||
mirror_interval=镜像同步周期(小时)
|
||||
mirror_address=镜像地址
|
||||
mirror_address_desc=请在镜像地址中写入必要的用户凭据信息。
|
||||
watchers=关注者
|
||||
stargazers=称赞者
|
||||
forks=派生仓库
|
||||
|
||||
form.reach_limit_of_creation=该用户已经达到允许创建 %d 个仓库的最大上限。
|
||||
form.name_reserved=仓库名称 '%s' 是被保留的。
|
||||
form.name_pattern_not_allowed=仓库名称不允许 '%s' 的格式。
|
||||
|
||||
@@ -369,6 +375,7 @@ migrate.permission_denied=您没有获得导入本地仓库的权限。
|
||||
migrate.invalid_local_path=无效的本地路径,不存在或不是一个目录!
|
||||
migrate.failed=迁移失败:%v
|
||||
|
||||
mirror_from=镜像自地址
|
||||
forked_from=派生自
|
||||
fork_from_self=无法派生已经拥有的仓库!
|
||||
copy_link=复制链接
|
||||
@@ -506,9 +513,9 @@ pulls.merged=已合并
|
||||
pulls.has_merged=该合并请求已经成功合并!
|
||||
pulls.data_broken=该合并请求的数据由于派生仓库的相关信息被删除而被破坏。
|
||||
pulls.is_checking=该合并请求正在进行冲突检查,请稍后再刷新页面。
|
||||
pulls.can_auto_merge_desc=您可以实现该合并请求的自动合并操作。
|
||||
pulls.cannot_auto_merge_desc=因为代码提交存在冲突,您无法对该合并请求执行自动合并操作。
|
||||
pulls.cannot_auto_merge_helper=请使用命令行工具来解决冲突。
|
||||
pulls.can_auto_merge_desc=该合并请求可以进行自动合并操作。
|
||||
pulls.cannot_auto_merge_desc=该合并请求存在冲突,无法进行自动合并操作。
|
||||
pulls.cannot_auto_merge_helper=请手动拉取代码变更以解决冲突。
|
||||
pulls.merge_pull_request=合并请求
|
||||
pulls.open_unmerged_pull_exists=`由于已经存在来自相同仓库和合并信息的未合并请求(#%d),您无法执行重新开启操作。`
|
||||
|
||||
@@ -563,6 +570,9 @@ settings.update_settings=更新仓库设置
|
||||
settings.change_reponame_prompt=该操作将会影响到所有与该仓库有关的链接
|
||||
settings.advanced_settings=高级设置
|
||||
settings.wiki_desc=启用 Wiki 以允许用户协作文档
|
||||
settings.use_external_wiki=使用外部 Wiki
|
||||
settings.external_wiki_url=外部 Wiki 链接
|
||||
settings.external_wiki_url_desc=当访问者单击分页标签时,将会被重定向到该链接。
|
||||
settings.issues_desc=启用内置的轻量级工单管理系统
|
||||
settings.use_external_issue_tracker=使用外部的工单管理系统
|
||||
settings.tracker_url_format=外部工单管理系统的 URL 格式
|
||||
@@ -851,6 +861,8 @@ users.auth_login_name=认证登录名称
|
||||
users.password_helper=将值留空使其保持不变。
|
||||
users.update_profile_success=该用户信息更新成功!
|
||||
users.edit_account=编辑用户信息
|
||||
users.max_repo_creation=最大允许创建仓库数量
|
||||
users.max_repo_creation_desc=(设置为 -1 表示使用全局默认值)
|
||||
users.is_activated=该用户已被激活
|
||||
users.is_admin=该用户具有管理员权限
|
||||
users.allow_git_hook=该用户具有创建 Git 钩子的权限
|
||||
@@ -1018,7 +1030,7 @@ comment_issue=`评论了工单 <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
merge_pull_request=`合并了合并请求 <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo=将仓库 <code>%s</code> 转移至 <a href="%s">%s</a>
|
||||
push_tag=推送了标签 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
|
||||
compare_2_commits=查看 2 次提交的内容对比
|
||||
compare_commits=对比 %d 次代码提交
|
||||
|
||||
[tool]
|
||||
ago=之前
|
||||
|
||||
@@ -28,6 +28,7 @@ organization=組織
|
||||
mirror=鏡像
|
||||
new_repo=創建新的倉庫
|
||||
new_migrate=遷移外部倉庫
|
||||
new_mirror=New Mirror
|
||||
new_fork=新的派生倉庫
|
||||
new_org=創建新的組織
|
||||
manage_org=管理我的組織
|
||||
@@ -53,8 +54,8 @@ code=程式碼
|
||||
[install]
|
||||
install=安裝頁面
|
||||
title=首次執行安裝程序
|
||||
docker_helper=If you're running Gogs inside Docker, please read <a target="_blank" href="%s">Guidelines</a> carefully before you change anything in this page!
|
||||
requite_db_desc=Gogs requires MySQL, PostgreSQL, SQLite3 or TiDB.
|
||||
docker_helper=如果您正在使用 Docker 容器運行 Gogs,請務必先仔細閱讀 <a target="_blank" href="%s">官方文檔</a> 後再對本頁面進行填寫。
|
||||
requite_db_desc=Gogs 要求安裝 MySQL、PostgreSQL、SQLite3 或 TiDB。
|
||||
db_title=數據庫設置
|
||||
db_type=數據庫類型
|
||||
host=數據庫主機
|
||||
@@ -64,11 +65,11 @@ db_name=數據庫名稱
|
||||
db_helper=如果您使用 MySQL,請使用 INNODB 引擎以及 utf8_general_ci 字符集。
|
||||
ssl_mode=SSL 模式
|
||||
path=數據庫文件路徑
|
||||
sqlite_helper=The file path of SQLite3 or TiDB database.
|
||||
err_empty_db_path=SQLite3 or TiDB database path cannot be empty.
|
||||
err_invalid_tidb_name=TiDB database name does not allow characters "." and "-".
|
||||
no_admin_and_disable_registration=You cannot disable registration without creating an admin account.
|
||||
err_empty_admin_password=Admin password cannot be empty.
|
||||
sqlite_helper=SQLite3 或 TiDB 的數據庫路徑。
|
||||
err_empty_db_path=SQLite3 或 TiDB 的數據庫路徑不能為空。
|
||||
err_invalid_tidb_name=TiDB 數據庫名稱不允許包含字符 "." 或 "-" 。
|
||||
no_admin_and_disable_registration=您不能夠在未創建管理員用戶的情況下禁止註冊。
|
||||
err_empty_admin_password=管理員密碼不能為空。
|
||||
|
||||
general_title=應用基本設置
|
||||
app_name=應用名稱
|
||||
@@ -102,8 +103,8 @@ disable_gravatar=禁用 Gravatar 服務
|
||||
disable_gravatar_popup=禁用 Gravatar 和自定義源,僅使用由用戶上傳或默認的頭像。
|
||||
disable_registration=禁止用戶自主註冊
|
||||
disable_registration_popup=禁止用戶自主註冊功能,只有管理員可以添加帳號。
|
||||
enable_captcha=Enable Captcha
|
||||
enable_captcha_popup=Require validate captcha for user self-registration.
|
||||
enable_captcha=啟用驗證碼服務
|
||||
enable_captcha_popup=要求在用戶註冊時輸入驗證碼
|
||||
require_sign_in_view=啓用登錄訪問限制
|
||||
require_sign_in_view_popup=只有已登錄的用戶才能夠訪問頁面,否則將只能看到登錄或註冊頁面。
|
||||
admin_setting_desc=創建管理員帳號並不是必須的,因為 ID=1 的用戶將自動獲得管理員權限。
|
||||
@@ -111,7 +112,7 @@ admin_title=管理員帳號設置
|
||||
admin_name=管理員用戶名
|
||||
admin_password=管理員密碼
|
||||
confirm_password=確認密碼
|
||||
admin_email=Admin Email
|
||||
admin_email=管理員郵箱
|
||||
install_gogs=立即安裝
|
||||
test_git_failed=無法識別 'git' 命令:%v
|
||||
sqlite3_not_available=您所使用的發行版本不支持 SQLite3,請從 %s 下載官方構建版,而不是 gobuild 版本。
|
||||
@@ -160,11 +161,11 @@ reset_password_helper=單擊此處重置密碼
|
||||
password_too_short=密碼長度不能少於 6 位!
|
||||
|
||||
[mail]
|
||||
activate_account=Please activate your account
|
||||
activate_email=Verify your email address
|
||||
reset_password=Reset your password
|
||||
register_success=Registration successful, welcome
|
||||
register_notify=Welcome on board
|
||||
activate_account=請激活您的帳戶
|
||||
activate_email=請驗證您的郵箱地址
|
||||
reset_password=重置密碼
|
||||
register_success=註冊成功,歡迎使用
|
||||
register_notify=歡迎使用
|
||||
|
||||
[modal]
|
||||
yes=確認操作
|
||||
@@ -192,7 +193,7 @@ min_size_error=長度最小為 %s 個字符。
|
||||
max_size_error=長度最大為 %s 個字符。
|
||||
email_error=不是一個有效的郵箱地址。
|
||||
url_error=不是一個有效的 URL。
|
||||
include_error=` must contain substring '%s'.`
|
||||
include_error=必須包含子字符串 '%s'。
|
||||
unknown_error=未知錯誤:
|
||||
captcha_incorrect=驗證碼未匹配。
|
||||
password_not_match=密碼與確認密碼未匹配。
|
||||
@@ -247,13 +248,14 @@ uid=用戶 ID
|
||||
|
||||
public_profile=公開信息
|
||||
profile_desc=您的郵箱地址將會被公開,並被用於接收帳戶的所有提醒和通知。
|
||||
password_username_disabled=Non-local type users are not allowed to change their username.
|
||||
full_name=自定義名稱
|
||||
website=個人網站
|
||||
location=所在地區
|
||||
update_profile=更新信息
|
||||
update_profile_success=您的個人信息更新成功!
|
||||
change_username=用戶名將被修改
|
||||
change_username_prompt=This change will affect the way how links relate to your account.
|
||||
change_username_prompt=該操作將會影響到所有與您帳戶有關的鏈接
|
||||
continue=繼續操作
|
||||
cancel=取消操作
|
||||
|
||||
@@ -268,9 +270,10 @@ update_avatar_success=您的頭像設置更新成功!
|
||||
change_password=修改密碼
|
||||
old_password=當前密碼
|
||||
new_password=新的密碼
|
||||
retype_new_password=Retype New Password
|
||||
retype_new_password=重新輸入新的密碼
|
||||
password_incorrect=當前密碼不正確!
|
||||
change_password_success=密碼修改成功!您現在可以使用新的密碼登錄。
|
||||
password_change_disabled=Non-local type users are not allowed to change their password.
|
||||
|
||||
emails=電子郵件地址
|
||||
manage_emails=管理電子郵件地址
|
||||
@@ -278,9 +281,9 @@ email_desc=您的主要邮箱地址将被用于通知提醒和其它操作。
|
||||
primary=主要
|
||||
primary_email=设为主要
|
||||
delete_email=刪除
|
||||
email_deletion=Email Deletion
|
||||
email_deletion_desc=Deleting this email address will remove related information from your account. Do you want to continue?
|
||||
email_deletion_success=Email has been deleted successfully!
|
||||
email_deletion=刪除郵箱
|
||||
email_deletion_desc=刪除該郵箱地址將會移除所有相關的信息。是否繼續?
|
||||
email_deletion_success=成功刪除郵箱!
|
||||
add_new_email=添加新的電子郵件地址
|
||||
add_email=添加電子郵件
|
||||
add_email_confirmation_sent=一封待確認的電子郵件已發送到 '%s',請在%d 小時內檢查您的收件箱,並完成確認過程。
|
||||
@@ -335,7 +338,7 @@ repo_name=倉庫名稱
|
||||
repo_name_helper=偉大的倉庫名稱一般都較短、令人深刻並且 <strong>獨一無二</strong> 的。
|
||||
visibility=可見度
|
||||
visiblity_helper=該倉庫為 <span class="ui red text">私有的</span>
|
||||
visiblity_helper_forced=Site admin has forced all new repositories to be <span class="ui red text">Private</span>
|
||||
visiblity_helper_forced=網站管理員已強制要求所有新建倉庫必須為 <span class="ui red text">私有的</span>
|
||||
visiblity_fork_helper=(修改該值將會影響到所有派生倉庫)
|
||||
clone_helper=不知道如何操作?訪問 <a target="_blank"href="%s"> 帮助説明</a> !
|
||||
fork_repo=派生倉庫
|
||||
@@ -343,19 +346,22 @@ fork_from=派生自
|
||||
fork_visiblity_helper=派生倉庫無法修改可見性。
|
||||
repo_desc=倉庫描述
|
||||
repo_lang=倉庫語言
|
||||
repo_lang_helper=Select .gitignore files
|
||||
repo_lang_helper=請選擇 .gitignore 文件
|
||||
license=授權許可
|
||||
license_helper=請選擇授權許可文件
|
||||
readme=Readme
|
||||
readme_helper=Select a readme template
|
||||
auto_init=Initialize this repository with selected files and template
|
||||
readme_helper=請選擇readme模板
|
||||
auto_init=使用選定的文件和模板初始化倉庫
|
||||
create_repo=創建倉庫
|
||||
default_branch=默認分支
|
||||
mirror_interval=鏡像同步周期(小時)
|
||||
watchers=Watchers
|
||||
stargazers=Stargazers
|
||||
forks=Forks
|
||||
mirror_address=Mirror Address
|
||||
mirror_address_desc=Please include necessary user credentials in the address.
|
||||
watchers=關注者
|
||||
stargazers=稱讚者
|
||||
forks=派生倉庫
|
||||
|
||||
form.reach_limit_of_creation=The owner has reached maximum creation limit of %d repositories.
|
||||
form.name_reserved=倉庫名稱 '%s' 是被保留的。
|
||||
form.name_pattern_not_allowed=倉庫名稱不允許 '%s' 的格式。
|
||||
|
||||
@@ -365,15 +371,16 @@ migrate_type_helper=該倉庫將是一個 <span class="text blue">鏡像</span>
|
||||
migrate_repo=遷移倉庫
|
||||
migrate.clone_address=複製地址
|
||||
migrate.clone_address_desc=該地址可以是 HTTP/HTTPS/GIT URL 或本地服務器路徑。
|
||||
migrate.permission_denied=You are not allowed to import local repositories.
|
||||
migrate.permission_denied=您並沒有導入本地倉庫的權限。
|
||||
migrate.invalid_local_path=無效的本地路徑,該路徑不存在或不是一個目錄!
|
||||
migrate.failed=Migration failed: %v
|
||||
migrate.failed=遷移失敗:%v
|
||||
|
||||
mirror_from=mirror from
|
||||
forked_from=派生自
|
||||
fork_from_self=無法派生已經擁有的倉庫!
|
||||
copy_link=複製連結
|
||||
copy_link_success=Copied!
|
||||
copy_link_error=Press ⌘-C or Ctrl-C to copy
|
||||
copy_link_success=複製成功!
|
||||
copy_link_error=請按下 ⌘-C 或 Ctrl-C 複製
|
||||
copied=複製成功
|
||||
unwatch=取消關註
|
||||
watch=關註
|
||||
@@ -386,16 +393,16 @@ quick_guide=快速幫助
|
||||
clone_this_repo=複製當前倉庫
|
||||
create_new_repo_command=從命令行創建一個新的倉庫
|
||||
push_exist_repo=從命令行推送已經創建的倉庫
|
||||
repo_is_empty=This repository is empty, please come back later!
|
||||
repo_is_empty=這倉庫不包含任何內容,請稍後再訪問!
|
||||
|
||||
code=Code
|
||||
code=代碼
|
||||
branch=分支
|
||||
tree=目錄樹
|
||||
filter_branch_and_tag=Filter branch or tag
|
||||
filter_branch_and_tag=過濾分支或標籤
|
||||
branches=分支列表
|
||||
tags=標籤列表
|
||||
issues=問題管理
|
||||
pulls=Pull Requests
|
||||
pulls=合併請求
|
||||
labels=標籤
|
||||
milestones=里程碑
|
||||
commits=提交歷史
|
||||
@@ -450,7 +457,7 @@ issues.filter_sort.recentupdate=最近更新
|
||||
issues.filter_sort.leastupdate=最少更新
|
||||
issues.filter_sort.mostcomment=最多評論
|
||||
issues.filter_sort.leastcomment=最少評論
|
||||
issues.opened_by=opened %[1]s by <a href="%[2]s">%[3]s</a>
|
||||
issues.opened_by=由 <a href="%[2]s">%[3]s</a> 與 %[1]s創建
|
||||
issues.opened_by_fake=由 %[2]s 於 %[1]s創建
|
||||
issues.previous=上一頁
|
||||
issues.next=下一頁
|
||||
@@ -466,7 +473,7 @@ issues.reopen_comment_issue=重新開啟及評論
|
||||
issues.create_comment=評論
|
||||
issues.closed_at=`於 <a id="%[1]s" href="#%[1]s">%[2]s</a> 關閉`
|
||||
issues.reopened_at=`於 <a id="%[1]s" href="#%[1]s">%[2]s</a> 重新開啟`
|
||||
issues.commit_ref_at=`referenced this issue from a commit <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commit_ref_at=`在代碼提交 <a id="%[1]s" href="#%[1]s">%[2]s</a> 中引用了該問題`
|
||||
issues.poster=發佈者
|
||||
issues.admin=管理員
|
||||
issues.owner=所有者
|
||||
@@ -486,31 +493,31 @@ issues.label_deletion=刪除標籤
|
||||
issues.label_deletion_desc=刪除該標籤將會移除所有問題中相關的訊息。是否繼續?
|
||||
issues.label_deletion_success=標籤刪除成功!
|
||||
|
||||
pulls.new=New Pull Request
|
||||
pulls.new=創建合併請求
|
||||
pulls.compare_changes=對比文件變化
|
||||
pulls.compare_changes_desc=對比兩個分支間的文件變化及發起一個合併請求。
|
||||
pulls.compare_base=base
|
||||
pulls.compare_compare=compare
|
||||
pulls.filter_branch=Filter branch
|
||||
pulls.compare_base=基準分支
|
||||
pulls.compare_compare=對比文件變化
|
||||
pulls.filter_branch=過濾分支
|
||||
pulls.no_results=未找到結果
|
||||
pulls.nothing_to_compare=There is nothing to compare because base and head branches are even.
|
||||
pulls.has_pull_request=`There is already a pull request between these two targets: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
|
||||
pulls.create=Create Pull Request
|
||||
pulls.title_desc=wants to merge %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code>
|
||||
pulls.merged_title_desc=merged %[1]d commits from <code>%[2]s</code> into <code>%[3]s</code> %[4]s
|
||||
pulls.tab_conversation=Conversation
|
||||
pulls.tab_commits=Commits
|
||||
pulls.tab_files=Files changed
|
||||
pulls.reopen_to_merge=Please reopen this pull request to perform merge operation.
|
||||
pulls.merged=Merged
|
||||
pulls.has_merged=This pull request has been merged successfully!
|
||||
pulls.data_broken=Data of this pull request has been broken due to deletion of fork information.
|
||||
pulls.is_checking=The conflict checking is still in progress, please refresh page in few moments.
|
||||
pulls.can_auto_merge_desc=You can perform auto-merge operation on this pull request.
|
||||
pulls.cannot_auto_merge_desc=You can't perform auto-merge operation because there are conflicts between commits.
|
||||
pulls.cannot_auto_merge_helper=Please use command line tool to solve it.
|
||||
pulls.merge_pull_request=Merge Pull Request
|
||||
pulls.open_unmerged_pull_exists=`You can't perform reopen operation because there is already an open pull request (#%d) from same repository with same merge information and is waiting for merging.`
|
||||
pulls.nothing_to_compare=基準和對比分支代碼已經同步,無需進行對比。
|
||||
pulls.has_pull_request=`已經存在目標分支的合併請求:<a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>`
|
||||
pulls.create=創建合併請求
|
||||
pulls.title_desc=請求將 %[1]d 次代碼提交從 <code>%[2]s</code> 合併至 <code>%[3]s</code>
|
||||
pulls.merged_title_desc=於 %[4]s 將 %[1]d 次代碼提交從 <code>%[2]s</code>合併至 <code>%[3]s</code>
|
||||
pulls.tab_conversation=對話內容
|
||||
pulls.tab_commits=代碼提交
|
||||
pulls.tab_files=文件變動
|
||||
pulls.reopen_to_merge=請重新開啟合併請求來完成合併操作。
|
||||
pulls.merged=已合併
|
||||
pulls.has_merged=該合併請求已經成功合併!
|
||||
pulls.data_broken=該合併請求的數據由於派生倉庫的相關信息被刪除而被破壞。
|
||||
pulls.is_checking=該合併請求正在進行衝突檢查,請稍後再刷新頁面。
|
||||
pulls.can_auto_merge_desc=This pull request can be merged automatically.
|
||||
pulls.cannot_auto_merge_desc=This pull request can't be merged automatically because there are conflicts.
|
||||
pulls.cannot_auto_merge_helper=Please merge manually in order to resolve the conflicts.
|
||||
pulls.merge_pull_request=合併請求
|
||||
pulls.open_unmerged_pull_exists=`由於已經存在來自相同倉庫和合併信息的未合併請求(#%d),您無法執行重新開啟操作。`
|
||||
|
||||
milestones.new=新的里程碑
|
||||
milestones.open_tab=%d 開啟中
|
||||
@@ -537,20 +544,20 @@ milestones.deletion_desc=刪除該里程碑將會移除所有問題中相關信
|
||||
milestones.deletion_success=里程碑刪除成功!
|
||||
|
||||
wiki=Wiki
|
||||
wiki.welcome=Welcome to Wiki!
|
||||
wiki.welcome_desc=Wiki is the place where you would like to document your project together and make it better.
|
||||
wiki.create_first_page=Create the first page
|
||||
wiki.page=Page
|
||||
wiki.filter_page=Filter page
|
||||
wiki.new_page=Create New Page
|
||||
wiki.default_commit_message=Write a note about this update (optional).
|
||||
wiki.save_page=Save Page
|
||||
wiki.last_commit_info=%s edited this page %s
|
||||
wiki.edit_page_button=Edit
|
||||
wiki.new_page_button=New Page
|
||||
wiki.page_already_exists=Wiki page with same name already exists.
|
||||
wiki.pages=Pages
|
||||
wiki.last_updated=Last updated %s
|
||||
wiki.welcome=歡迎使用 Wiki!
|
||||
wiki.welcome_desc=Wiki 是用於共同協作文檔的地方,清晰的文檔可以幫助其他人深入了解您的項目。
|
||||
wiki.create_first_page=創建第一個頁面
|
||||
wiki.page=頁面
|
||||
wiki.filter_page=過濾頁面
|
||||
wiki.new_page=創建新的頁面
|
||||
wiki.default_commit_message=關於此次修改的說明(可選)。
|
||||
wiki.save_page=保存頁面
|
||||
wiki.last_commit_info=%s 於 %s 修改了此頁面
|
||||
wiki.edit_page_button=修改
|
||||
wiki.new_page_button=新的頁面
|
||||
wiki.page_already_exists=相同名稱的 Wiki 頁面已經存在。
|
||||
wiki.pages=所有頁面
|
||||
wiki.last_updated=最後更新於 %s
|
||||
|
||||
settings=倉庫設置
|
||||
settings.options=基本設置
|
||||
@@ -560,29 +567,32 @@ settings.githooks=管理 Git 鉤子
|
||||
settings.basic_settings=基本設置
|
||||
settings.site=官方網站
|
||||
settings.update_settings=更新倉庫設置
|
||||
settings.change_reponame_prompt=This change will affect how links relate to the repository.
|
||||
settings.advanced_settings=Advanced Settings
|
||||
settings.wiki_desc=Enable wiki to allow people write documents
|
||||
settings.issues_desc=Enable builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker=Use external issue tracker
|
||||
settings.tracker_url_format=External Issue Tracker URL Format
|
||||
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc=Enable pull requests to accept public contributions
|
||||
settings.change_reponame_prompt=該操作將會影響到所有與該倉庫有關的鏈接
|
||||
settings.advanced_settings=高級設置
|
||||
settings.wiki_desc=啟用 Wiki 以允許用戶協作文檔
|
||||
settings.use_external_wiki=Use external wiki
|
||||
settings.external_wiki_url=External Wiki URL
|
||||
settings.external_wiki_url_desc=Visitors will be redirected to URL when they click on the tab.
|
||||
settings.issues_desc=啟用內置的輕量級問題管理系統
|
||||
settings.use_external_issue_tracker=使用外部的問題管理系統
|
||||
settings.tracker_url_format=外部問題管理系統的 URL 格式
|
||||
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分別作為用戶名、倉庫名和問題索引的占位符。
|
||||
settings.pulls_desc=啟用合併請求以接受社區貢獻
|
||||
settings.danger_zone=危險操作區
|
||||
settings.transfer=轉移倉庫所有權
|
||||
settings.transfer_desc=您可以將倉庫轉移至您擁有管理員權限的帳戶或組織。
|
||||
settings.new_owner_has_same_repo=新的倉庫擁有者已經存在同名倉庫!
|
||||
settings.delete=刪除本倉庫
|
||||
settings.delete_desc=刪除倉庫操作不可逆轉,請三思而後行。
|
||||
settings.transfer_notices_1=- You will lose access if new owner is a individual user.
|
||||
settings.transfer_notices_2=- You will conserve access if new owner is an organization and if you're one of the owners.
|
||||
settings.transfer_form_title=Please enter following information to confirm your operation:
|
||||
settings.delete_notices_1=- This operation <strong>CANNOT</strong> be undone.
|
||||
settings.delete_notices_2=- This operation will permanently delete the everything of this repository, including Git data, issues, comments and accesses of collaborators.
|
||||
settings.delete_notices_fork_1=- If this repository is public, all forks will be became independent after deletion.
|
||||
settings.delete_notices_fork_2=- If this repository is private, all forks will be removed at the same time.
|
||||
settings.delete_notices_fork_3=- If you want to keep all forks after deletion, please change visibility of this repository to public first.
|
||||
settings.deletion_success=Repository has been deleted successfully!
|
||||
settings.transfer_notices_1=- 如果您將倉庫轉移給個人用戶,您將會丟失操作權限。
|
||||
settings.transfer_notices_2=- 如果您將倉庫轉移給您是所有者的組織,您的操作權限將被保留。
|
||||
settings.transfer_form_title=請輸入以下信息以確認您的操作:
|
||||
settings.delete_notices_1=- 此操作 <strong>不可以</strong> 被回滾。
|
||||
settings.delete_notices_2=- 此操作將永久刪除該倉庫,包括 Git 數據、 問題、 評論和協作者的操作權限。
|
||||
settings.delete_notices_fork_1=- 如果該倉庫為公開的,則在刪除倉庫後所有的派生倉庫都將轉換成獨立的倉庫。
|
||||
settings.delete_notices_fork_2=- 如果該倉庫為私有,則會同時刪除所有的派生倉庫。
|
||||
settings.delete_notices_fork_3=- 如果您想要保留派生倉庫,請先將可見性修改為公開的後再進行刪除操作。
|
||||
settings.deletion_success=倉庫刪除成功!
|
||||
settings.update_settings_success=倉庫設置更新成功!
|
||||
settings.transfer_owner=新擁有者
|
||||
settings.make_transfer=確認轉移倉庫
|
||||
@@ -591,21 +601,21 @@ settings.confirm_delete=確認刪除倉庫
|
||||
settings.add_collaborator=增加新的協作者
|
||||
settings.add_collaborator_success=成功添加新的協作者!
|
||||
settings.remove_collaborator_success=被操作的協作者已經被收回權限!
|
||||
settings.search_user_placeholder=Search user...
|
||||
settings.search_user_placeholder=搜索用戶...
|
||||
settings.user_is_org_member=被操作的用戶是組織成員,因此無法添加為協作者!
|
||||
settings.add_webhook=添加 Web 鉤子
|
||||
settings.hooks_desc=Web 鉤子允許您設定在 Gogs 上發生指定事件時對指定 URL 發送 POST 通知。查看 <a target="_blank" href="%s">Webhooks 文檔</a> 獲取更多信息。
|
||||
settings.webhook_deletion=Delete Webhook
|
||||
settings.webhook_deletion_desc=Delete this webhook will remove its information and all delivery history. Do you want to continue?
|
||||
settings.webhook_deletion_success=Webhook has been deleted successfully!
|
||||
settings.webhook.test_delivery=Test Delivery
|
||||
settings.webhook.test_delivery_desc=Send a fake push event delivery to test your webhook settings
|
||||
settings.webhook.test_delivery_success=Test webhook has been added to delivery queue. It may taks few seconds before it shows up in the delivery history.
|
||||
settings.webhook.request=Request
|
||||
settings.webhook.response=Response
|
||||
settings.webhook.headers=Headers
|
||||
settings.webhook.payload=Payload
|
||||
settings.webhook.body=Body
|
||||
settings.webhook_deletion=刪除 Web 鉤子
|
||||
settings.webhook_deletion_desc=刪除該 Web 鉤子將會刪除與其有關的信息和推送歷史。是否繼續?
|
||||
settings.webhook_deletion_success=Web 鉤子刪除成功!
|
||||
settings.webhook.test_delivery=測試推送
|
||||
settings.webhook.test_delivery_desc=生成並推送一個模擬的 Push 事件
|
||||
settings.webhook.test_delivery_success=測試推送已經加入到隊列,請耐心等待數秒再刷新推送記錄。
|
||||
settings.webhook.request=請求內容
|
||||
settings.webhook.response=響應內容
|
||||
settings.webhook.headers=標題
|
||||
settings.webhook.payload=推送內容
|
||||
settings.webhook.body=響應內容
|
||||
settings.githooks_desc=Git 鉤子是由 Git 本身提供的功能,以下為 Gogs 所支持的鉤子列表。
|
||||
settings.githook_edit_desc=如果鉤子未啟動,則會顯示樣例文件中的內容。如果想要刪除某個鉤子,則提交空白文本即可。
|
||||
settings.githook_name=鉤子名稱
|
||||
@@ -615,17 +625,17 @@ settings.add_webhook_desc=我們會通過 <code>POST</code> 請求將訂閱事
|
||||
settings.payload_url=推送地址
|
||||
settings.content_type=數據格式
|
||||
settings.secret=密鑰文本
|
||||
settings.slack_username=Username
|
||||
settings.slack_icon_url=Icon URL
|
||||
settings.slack_color=Color
|
||||
settings.slack_username=服務名稱
|
||||
settings.slack_icon_url=圖標 URL
|
||||
settings.slack_color=顏色代碼
|
||||
settings.event_desc=請設置您希望觸發 Web 鉤子的事件:
|
||||
settings.event_push_only=只推送 <code>push</code> 事件。
|
||||
settings.event_send_everything=I need <strong>everything</strong>.
|
||||
settings.event_choose=Let me choose what I need.
|
||||
settings.event_create=Create
|
||||
settings.event_create_desc=Branch, or tag created
|
||||
settings.event_push=Push
|
||||
settings.event_push_desc=Git push to a repository
|
||||
settings.event_send_everything=推送 <strong>所有</strong> 事件
|
||||
settings.event_choose=讓我選擇我的需要
|
||||
settings.event_create=創建
|
||||
settings.event_create_desc=創建分支或標籤
|
||||
settings.event_push=推送
|
||||
settings.event_push_desc=Git 倉庫推送
|
||||
settings.active=是否激活
|
||||
settings.active_helper=當指定事件發生時我們將會觸發此 Web 鉤子。
|
||||
settings.add_hook_success=Web 鉤子添加成功!
|
||||
@@ -640,7 +650,7 @@ settings.slack_domain=域名
|
||||
settings.slack_channel=頻道
|
||||
settings.deploy_keys=管理部署密鑰
|
||||
settings.add_deploy_key=添加部署密鑰
|
||||
settings.deploy_key_desc=Deploy key only has read-only access. It is not same as personal account SSH keys.
|
||||
settings.deploy_key_desc=部署密鑰僅具有隻讀權限,它在功能上和個人用戶的公開密鑰有本質區別。
|
||||
settings.no_deploy_keys=您還沒有添加任何部署密鑰。
|
||||
settings.title=標題
|
||||
settings.deploy_key_content=密鑰文本
|
||||
@@ -668,32 +678,32 @@ release.stable=穩定
|
||||
release.edit=編輯
|
||||
release.ahead=在該版本發佈之後已有 <strong>%d</strong> 次代碼提交到 %s 分支
|
||||
release.source_code=源代碼
|
||||
release.new_subheader=Publish releases to iterate product.
|
||||
release.edit_subheader=Detailed change log can help users understand what has been improved.
|
||||
release.new_subheader=發布版本對產品進行迭代。
|
||||
release.edit_subheader=詳細的變更日誌可以幫助用戶更好地了解產品做了哪些改進。
|
||||
release.tag_name=標籤名稱
|
||||
release.target=目標分支
|
||||
release.tag_helper=選擇或創建一個已存在的標籤
|
||||
release.title=Title
|
||||
release.content=Content
|
||||
release.title=標題
|
||||
release.content=內容
|
||||
release.write=內容編輯
|
||||
release.preview=效果預覽
|
||||
release.loading=正在加載...
|
||||
release.prerelease_desc=這是一個預發佈版本
|
||||
release.prerelease_helper=我們會告知用戶不建議將本發佈投入生產環境使用。
|
||||
release.cancel=Cancel
|
||||
release.cancel=取消
|
||||
release.publish=發佈版本
|
||||
release.save_draft=保在草稿
|
||||
release.edit_release=編輯發佈信息
|
||||
release.delete_release=Delete This Release
|
||||
release.deletion=Release Deletion
|
||||
release.deletion_desc=Deleting this release will delete the corresponding Git tag. Do you want to continue?
|
||||
release.deletion_success=Release has been deleted successfully!
|
||||
release.delete_release=刪除此次發布
|
||||
release.deletion=刪除版本發布操作
|
||||
release.deletion_desc=刪除該版本發布將會移除相應的 Git 標籤。是否繼續?
|
||||
release.deletion_success=版本發布刪除成功!
|
||||
release.tag_name_already_exist=已經存在使用相同標籤的發佈版本。
|
||||
release.downloads=Downloads
|
||||
release.downloads=下載附件
|
||||
|
||||
[org]
|
||||
org_name_holder=組織名稱
|
||||
org_full_name_holder=Organization Full Name
|
||||
org_full_name_holder=組織全名
|
||||
org_name_helper=偉大的組織都有一個簡短而寓意深刻的名字。
|
||||
create_org=創建組織
|
||||
repo_updated=最後更新於
|
||||
@@ -720,8 +730,8 @@ settings.website=官方網站
|
||||
settings.location=所在地區
|
||||
settings.update_settings=更新組織設置
|
||||
settings.update_setting_success=組織設置更新成功!
|
||||
settings.change_orgname_prompt=This change will affect how links relate to the organization.
|
||||
settings.update_avatar_success=Organization avatar setting has been updated successfully.
|
||||
settings.change_orgname_prompt=該操作將會影響到所有與該組織有關的鏈接
|
||||
settings.update_avatar_success=組織頭像更新成功!
|
||||
settings.delete=刪除組織
|
||||
settings.delete_account=刪除當前組織
|
||||
settings.delete_prompt=刪除操作會永久清除該組織的信息,並且 <strong>不可恢復</strong>!
|
||||
@@ -730,17 +740,17 @@ settings.delete_org_title=組織刪除操作
|
||||
settings.delete_org_desc=該組織將被永久性刪除,您確定要繼續操作嗎?
|
||||
settings.hooks_desc=在此處添加的 Web 鉤子將會應用到該組織下的 <strong>所有倉庫</strong>。
|
||||
|
||||
members.membership_visibility=Membership Visibility:
|
||||
members.membership_visibility=成員可見性:
|
||||
members.public=公開成員
|
||||
members.public_helper=設為私有
|
||||
members.private=私有成員
|
||||
members.private_helper=設為公開
|
||||
members.member_role=Member Role:
|
||||
members.member_role=成員角色:
|
||||
members.owner=管理員
|
||||
members.member=普通成員
|
||||
members.remove=移除成員
|
||||
members.leave=離開組織
|
||||
members.invite_desc=Add a new member to %s:
|
||||
members.invite_desc=邀請新的用戶加入 %s:
|
||||
members.invite_now=立即邀請
|
||||
|
||||
teams.join=加入團隊
|
||||
@@ -765,7 +775,7 @@ teams.read_permission_desc=該團隊擁有對所屬倉庫的 <strong>讀取</str
|
||||
teams.write_permission_desc=該團隊擁有對所屬倉庫的 <strong>讀取</strong> 和 <strong>寫入</strong> 的權限。
|
||||
teams.admin_permission_desc=該團隊擁有一定的 <strong>管理</strong> 權限,團隊成員可以讀取、複製、推送以及添加其它倉庫協作者。
|
||||
teams.repositories=團隊倉庫
|
||||
teams.search_repo_placeholder=Search repository...
|
||||
teams.search_repo_placeholder=搜索倉庫...
|
||||
teams.add_team_repository=添加團隊倉庫
|
||||
teams.remove_repo=移除倉庫
|
||||
teams.add_nonexistent_repo=您嘗試添加到團隊的倉庫不存在,請先創建倉庫!
|
||||
@@ -779,9 +789,9 @@ authentication=授權認證管理
|
||||
config=應用配置管理
|
||||
notices=系統提示管理
|
||||
monitor=應用監控面版
|
||||
first_page=First
|
||||
last_page=Last
|
||||
total=Total: %d
|
||||
first_page=首頁
|
||||
last_page=末頁
|
||||
total=總計:%d
|
||||
|
||||
dashboard.statistic=應用統計數據
|
||||
dashboard.operations=管理員操作
|
||||
@@ -796,8 +806,8 @@ dashboard.delete_inactivate_accounts=刪除所有未激活帳戶
|
||||
dashboard.delete_inactivate_accounts_success=所有未激活帳號清除成功!
|
||||
dashboard.delete_repo_archives=刪除所有倉庫存檔
|
||||
dashboard.delete_repo_archives_success=所有倉庫存檔清除成功!
|
||||
dashboard.delete_missing_repos=Delete all repository records that lost Git files
|
||||
dashboard.delete_missing_repos_success=All repository records that lost Git files have been deleted successfully.
|
||||
dashboard.delete_missing_repos=刪除所有丟失 Git 文件的倉庫記錄
|
||||
dashboard.delete_missing_repos_success=成功刪除所有丟失 Git 文件的倉庫記錄!
|
||||
dashboard.git_gc_repos=對倉庫進行垃圾回收
|
||||
dashboard.git_gc_repos_success=所有倉庫的垃圾回收已成功完成!
|
||||
dashboard.resync_all_sshkeys=重新生成 '.ssh/authorized_keys' 文件(警告:不是 Gogs 的密鑰也會被刪除)
|
||||
@@ -842,24 +852,26 @@ users.activated=已激活
|
||||
users.admin=管理員
|
||||
users.repos=倉庫數
|
||||
users.created=創建時間
|
||||
users.send_register_notify=Send Registration Notification To User
|
||||
users.new_success=New account '%s' has been created successfully.
|
||||
users.send_register_notify=向用戶發送註冊通知郵件
|
||||
users.new_success=新用戶 '%s' 創建成功!
|
||||
users.edit=編輯
|
||||
users.auth_source=Authentication Source
|
||||
users.auth_source=認證源
|
||||
users.local=本地
|
||||
users.auth_login_name=Authentication Login Name
|
||||
users.password_helper=Leave it empty to remain unchanged.
|
||||
users.auth_login_name=認證登錄名稱
|
||||
users.password_helper=留空使其保持不變。
|
||||
users.update_profile_success=該用戶信息更新成功!
|
||||
users.edit_account=編輯用戶信息
|
||||
users.max_repo_creation=Maximum Repository Creation Limit
|
||||
users.max_repo_creation_desc=(Set -1 to use global default limit)
|
||||
users.is_activated=該用戶已被激活
|
||||
users.is_admin=該用戶具有管理員權限
|
||||
users.allow_git_hook=該帳戶具有創建 Git 鉤子的權限
|
||||
users.allow_import_local=This account has permissions to import local repositories
|
||||
users.allow_import_local=該用戶具有導入本地倉庫的權限
|
||||
users.update_profile=更新用戶信息
|
||||
users.delete_account=刪除該用戶
|
||||
users.still_own_repo=該帳戶仍然是某些倉庫的擁有者,您必須先轉移或刪除它們才能執行刪除帳戶操作!
|
||||
users.still_has_org=該帳戶仍舊是某些組織的成員,您必須先使其離開或刪除組織。
|
||||
users.deletion_success=Account has been deleted successfully!
|
||||
users.deletion_success=用戶刪除成功!
|
||||
|
||||
orgs.org_manage_panel=組織管理面版
|
||||
orgs.name=組織名稱
|
||||
@@ -874,49 +886,49 @@ repos.watches=關註數
|
||||
repos.stars=讚好數
|
||||
repos.issues=問題數
|
||||
|
||||
auths.auth_manage_panel=Authentication Manage Panel
|
||||
auths.new=Add New Source
|
||||
auths.auth_manage_panel=認證管理面板
|
||||
auths.new=添加新認證源
|
||||
auths.name=認證名稱
|
||||
auths.type=認證類型
|
||||
auths.enabled=已啟用
|
||||
auths.updated=最後更新時間
|
||||
auths.auth_type=Authentication Type
|
||||
auths.auth_name=Authentication Name
|
||||
auths.auth_type=認證類型
|
||||
auths.auth_name=認證名稱
|
||||
auths.domain=域名
|
||||
auths.host=主機地址
|
||||
auths.port=主機端口
|
||||
auths.bind_dn=綁定DN
|
||||
auths.bind_password=綁定密碼
|
||||
auths.bind_password_helper=Warning: This password is stored in plain text. Do not use a high privileged account.
|
||||
auths.user_base=User Search Base
|
||||
auths.bind_password_helper=警告:該密碼將會以明文的形式保存在數據庫中。請不要使用擁有高權限的帳戶!
|
||||
auths.user_base=用戶搜索基準
|
||||
auths.user_dn=User DN
|
||||
auths.attribute_username=Username attribute
|
||||
auths.attribute_username_placeholder=Leave empty to use sign-in form field value for user name.
|
||||
auths.attribute_username=用戶名屬性
|
||||
auths.attribute_username_placeholder=留空表示使用用戶登錄時所使用的用戶名
|
||||
auths.attribute_name=名子屬性
|
||||
auths.attribute_surname=姓氏屬性
|
||||
auths.attribute_mail=電子郵箱屬性
|
||||
auths.filter=使用者篩選器
|
||||
auths.admin_filter=管理者篩選器
|
||||
auths.ms_ad_sa=Ms Ad SA
|
||||
auths.smtp_auth=SMTP Authentication Type
|
||||
auths.smtp_auth=SMTP 驗證類型
|
||||
auths.smtphost=SMTP 主機地址
|
||||
auths.smtpport=SMTP 主機端口
|
||||
auths.allowed_domains=Allowed Domains
|
||||
auths.allowed_domains_helper=Leave it empty to not restrict any domains. Multiple domains should be separated by comma ','.
|
||||
auths.allowed_domains=域名白名單
|
||||
auths.allowed_domains_helper=留空表示不對域名做任何限制。多個域名之間需要使用逗號 ',' 分隔。
|
||||
auths.enable_tls=啟用 TLS 加密
|
||||
auths.skip_tls_verify=Skip TLS Verify
|
||||
auths.skip_tls_verify=忽略 TLS 驗證
|
||||
auths.pam_service_name=PAM 服務名稱
|
||||
auths.enable_auto_register=允許授權用戶自動註冊
|
||||
auths.tips=幫助提示
|
||||
auths.edit=Edit Authentication Setting
|
||||
auths.edit=編輯認證設置
|
||||
auths.activated=該授權認證已經啟用
|
||||
auths.new_success=New authentication '%s' has been added successfully.
|
||||
auths.update_success=Authentication setting has been updated successfully.
|
||||
auths.update=Update Authentication Setting
|
||||
auths.delete=Delete This Authentication
|
||||
auths.delete_auth_title=Authentication Deletion
|
||||
auths.delete_auth_desc=This authentication is going to be deleted, do you want to continue?
|
||||
auths.deletion_success=Authentication has been deleted successfully!
|
||||
auths.new_success=新的認證源 "%s" 添加成功!
|
||||
auths.update_success=認證設置更新成功!
|
||||
auths.update=更新認證設置
|
||||
auths.delete=刪除該認證
|
||||
auths.delete_auth_title=刪除認證操作
|
||||
auths.delete_auth_desc=該認證將被刪除。是否繼續?
|
||||
auths.deletion_success=認證源刪除成功!
|
||||
|
||||
config.server_config=服務器配置
|
||||
config.app_name=應用名稱
|
||||
@@ -940,7 +952,7 @@ config.db_user=數據庫用戶
|
||||
config.db_ssl_mode=SSL 模式
|
||||
config.db_ssl_mode_helper=(僅限 "postgres" 使用)
|
||||
config.db_path=數據庫路徑
|
||||
config.db_path_helper=(for "sqlite3" and "tidb")
|
||||
config.db_path_helper=(用於 "sqlite3" 和 "tidb")
|
||||
config.service_config=服務配置
|
||||
config.register_email_confirm=註冊電子郵件確認
|
||||
config.disable_register=關閉註冊功能
|
||||
@@ -948,8 +960,8 @@ config.show_registration_button=顯示註冊按鈕
|
||||
config.require_sign_in_view=強制登錄瀏覽
|
||||
config.enable_cache_avatar=開啟緩存頭像
|
||||
config.mail_notify=郵件通知提醒
|
||||
config.disable_key_size_check=Disable Minimum Key Size Check
|
||||
config.enable_captcha=Enable Captcha
|
||||
config.disable_key_size_check=禁用密鑰最小長度檢查
|
||||
config.enable_captcha=啟用驗證碼服務
|
||||
config.active_code_lives=激活用戶連結有效期
|
||||
config.reset_password_code_lives=重置密碼連結有效期
|
||||
config.webhook_config=Web 鉤子配置
|
||||
@@ -995,30 +1007,30 @@ monitor.start=開始時間
|
||||
monitor.execute_time=已執行時間
|
||||
|
||||
notices.system_notice_list=系統提示管理
|
||||
notices.view_detail_header=View Notice Detail
|
||||
notices.actions=Actions
|
||||
notices.select_all=Select All
|
||||
notices.deselect_all=Deselect All
|
||||
notices.inverse_selection=Inverse Selection
|
||||
notices.delete_selected=Delete Selected
|
||||
notices.delete_all=Delete All Notices
|
||||
notices.view_detail_header=查看提示詳情
|
||||
notices.actions=操作
|
||||
notices.select_all=選取全部
|
||||
notices.deselect_all=取消所有選取
|
||||
notices.inverse_selection=反向選取
|
||||
notices.delete_selected=刪除選取項
|
||||
notices.delete_all=刪除所有提示
|
||||
notices.type=提示類型
|
||||
notices.type_1=倉庫
|
||||
notices.desc=描述
|
||||
notices.op=操作
|
||||
notices.delete_success=System notices have been deleted successfully.
|
||||
notices.delete_success=系統提示刪除成功!
|
||||
|
||||
[action]
|
||||
create_repo=創建了倉庫 <a href="%s">%s</a>
|
||||
rename_repo=renamed repository from <code>%[1]s</code> to <a href="%[2]s">%[3]s</a>
|
||||
rename_repo=重新命名倉庫 <code>%[1]s</code> 為 <a href="%[2]s">%[3]s</a>
|
||||
commit_repo=推送了 <a href="%[1]s/src/%[2]s">%[3]s</a> 分支的代碼到 <a href="%[1]s">%[4]s</a>
|
||||
create_issue=`創建了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
create_pull_request=`created pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
create_pull_request=`創建了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
comment_issue=`評論了問題 <a href="%s/issues/%s">%s#%[2]s</a>`
|
||||
merge_pull_request=`merged pull request <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
merge_pull_request=`合併了合併請求 <a href="%s/pulls/%s">%s#%[2]s</a>`
|
||||
transfer_repo=將倉庫 <code>%s</code> 轉移至 <a href="%s">%s</a>
|
||||
push_tag=推送了標籤 <a href="%s/src/%s">%[2]s</a> 到 <a href="%[1]s">%[3]s</a>
|
||||
compare_2_commits=查看 2 次提交的內容對比
|
||||
compare_commits=View comparison for these %d commits
|
||||
|
||||
[tool]
|
||||
ago=之前
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Docker for Gogs
|
||||
|
||||
Visit [Docker Hub](https://hub.docker.com/r/gogs/gogs/) see all available tags.
|
||||
Visit [Docker Hub](https://hub.docker.com/r/gogs/gogs/) or [Quay](https://quay.io/repository/gogs/gogs) see all available tags.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -52,7 +52,7 @@ Most of settings are obvious and easy to understand, but there are some settings
|
||||
- **Repository Root Path**: keep it as default value `/home/git/gogs-repositories` because `start.sh` already made a symbolic link for you.
|
||||
- **Run User**: keep it as default value `git` because `start.sh` already setup a user with name `git`.
|
||||
- **Domain**: fill in with Docker container IP(e.g. `192.168.99.100`). But if you want to access your Gogs instance from a different physical machine, please fill in with the hostname or IP address of the Docker host machine.
|
||||
- **SSH Port**: Use the exposed port from Docker container. For example, your SSH server listens on `22` inside Docker, but you expose it by `10022:22`, then use `10022` for this value.
|
||||
- **SSH Port**: Use the exposed port from Docker container. For example, your SSH server listens on `22` inside Docker, but you expose it by `10022:22`, then use `10022` for this value. **Builtin SSH server is not recommended inside Docker Container**
|
||||
- **HTTP Port**: Use port you want Gogs to listen on inside Docker container. For example, your Gogs listens on `3000` inside Docker, and you expose it by `10080:3000`, but you still use `3000` for this value.
|
||||
- **Application URL**: Use combination of **Domain** and **exposed HTTP Port** values(e.g. `http://192.168.99.100:10080/`).
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ apk -U --no-progress add linux-pam-dev go@community gcc musl-dev
|
||||
mkdir -p ${GOPATH}/src/github.com/gogits/
|
||||
ln -s /app/gogs/ ${GOPATH}/src/github.com/gogits/gogs
|
||||
cd ${GOPATH}/src/github.com/gogits/gogs
|
||||
go get -v -tags "sqlite redis memcache cert pam"
|
||||
go build -tags "sqlite redis memcache cert pam"
|
||||
go get -v -tags "sqlite cert pam"
|
||||
go build -tags "sqlite cert pam"
|
||||
|
||||
# Cleanup GOPATH
|
||||
rm -r $GOPATH
|
||||
|
||||
4
gogs.go
4
gogs.go
@@ -1,4 +1,4 @@
|
||||
// +build go1.3
|
||||
// +build go1.4
|
||||
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
const APP_VER = "0.7.33.1205 Beta"
|
||||
const APP_VER = "0.8.10.1217"
|
||||
|
||||
func init() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
|
||||
@@ -17,10 +17,10 @@ import (
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/xorm"
|
||||
|
||||
"github.com/gogits/git-module"
|
||||
api "github.com/gogits/go-gogs-client"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/git"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
@@ -229,6 +229,28 @@ func NewPushCommits() *PushCommits {
|
||||
}
|
||||
}
|
||||
|
||||
func (pc *PushCommits) ToApiPayloadCommits(repoLink string) []*api.PayloadCommit {
|
||||
commits := make([]*api.PayloadCommit, len(pc.Commits))
|
||||
for i, cmt := range pc.Commits {
|
||||
author_username := ""
|
||||
author, err := GetUserByEmail(cmt.AuthorEmail)
|
||||
if err == nil {
|
||||
author_username = author.Name
|
||||
}
|
||||
commits[i] = &api.PayloadCommit{
|
||||
ID: cmt.Sha1,
|
||||
Message: cmt.Message,
|
||||
URL: fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1),
|
||||
Author: &api.PayloadAuthor{
|
||||
Name: cmt.AuthorName,
|
||||
Email: cmt.AuthorEmail,
|
||||
UserName: author_username,
|
||||
},
|
||||
}
|
||||
}
|
||||
return commits
|
||||
}
|
||||
|
||||
// AvatarLink tries to match user in database with e-mail
|
||||
// in order to show custom avatar, and falls back to general avatar link.
|
||||
func (push *PushCommits) AvatarLink(email string) string {
|
||||
@@ -413,15 +435,11 @@ func CommitRepoAction(
|
||||
} else {
|
||||
// if not the first commit, set the compareUrl
|
||||
if !strings.HasPrefix(oldCommitID, "0000000") {
|
||||
commit.CompareUrl = fmt.Sprintf("%s/%s/compare/%s...%s", repoUserName, repoName, oldCommitID, newCommitID)
|
||||
commit.CompareUrl = repo.ComposeCompareURL(oldCommitID, newCommitID)
|
||||
} else {
|
||||
isNewBranch = true
|
||||
}
|
||||
|
||||
// NOTE: limit to detect latest 100 commits.
|
||||
if len(commit.Commits) > 100 {
|
||||
commit.Commits = commit.Commits[len(commit.Commits)-100:]
|
||||
}
|
||||
if err = updateIssuesCommit(u, repo, repoUserName, repoName, commit.Commits); err != nil {
|
||||
log.Error(4, "updateIssuesCommit: %v", err)
|
||||
}
|
||||
@@ -469,30 +487,12 @@ func CommitRepoAction(
|
||||
|
||||
switch opType {
|
||||
case COMMIT_REPO: // Push
|
||||
commits := make([]*api.PayloadCommit, len(commit.Commits))
|
||||
for i, cmt := range commit.Commits {
|
||||
author_username := ""
|
||||
author, err := GetUserByEmail(cmt.AuthorEmail)
|
||||
if err == nil {
|
||||
author_username = author.Name
|
||||
}
|
||||
commits[i] = &api.PayloadCommit{
|
||||
ID: cmt.Sha1,
|
||||
Message: cmt.Message,
|
||||
URL: fmt.Sprintf("%s/commit/%s", repo.RepoLink(), cmt.Sha1),
|
||||
Author: &api.PayloadAuthor{
|
||||
Name: cmt.AuthorName,
|
||||
Email: cmt.AuthorEmail,
|
||||
UserName: author_username,
|
||||
},
|
||||
}
|
||||
}
|
||||
p := &api.PushPayload{
|
||||
Ref: refFullName,
|
||||
Before: oldCommitID,
|
||||
After: newCommitID,
|
||||
CompareUrl: setting.AppUrl + commit.CompareUrl,
|
||||
Commits: commits,
|
||||
Commits: commit.ToApiPayloadCommits(repo.FullRepoLink()),
|
||||
Repo: payloadRepo,
|
||||
Pusher: &api.PayloadAuthor{
|
||||
Name: pusher_name,
|
||||
|
||||
@@ -107,6 +107,19 @@ func (err ErrUserHasOrgs) Error() string {
|
||||
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
|
||||
}
|
||||
|
||||
type ErrReachLimitOfRepo struct {
|
||||
Limit int
|
||||
}
|
||||
|
||||
func IsErrReachLimitOfRepo(err error) bool {
|
||||
_, ok := err.(ErrReachLimitOfRepo)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrReachLimitOfRepo) Error() string {
|
||||
return fmt.Sprintf("user has reached maximum limit of repositories [limit: %d]", err.Limit)
|
||||
}
|
||||
|
||||
// __ __.__ __ .__
|
||||
// / \ / \__| | _|__|
|
||||
// \ \/\/ / | |/ / |
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
@@ -17,7 +18,7 @@ import (
|
||||
"golang.org/x/net/html/charset"
|
||||
"golang.org/x/text/transform"
|
||||
|
||||
"github.com/gogits/git-shell"
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
@@ -124,6 +125,7 @@ func ParsePatch(maxlines int, reader io.Reader) (*Diff, error) {
|
||||
// Diff data too large, we only show the first about maxlines lines
|
||||
if lineCount >= maxlines {
|
||||
log.Warn("Diff data too large")
|
||||
io.Copy(ioutil.Discard, reader)
|
||||
diff.Files = nil
|
||||
return diff, nil
|
||||
}
|
||||
@@ -244,8 +246,8 @@ func ParsePatch(maxlines int, reader io.Reader) (*Diff, error) {
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
}
|
||||
charsetLabel, err := base.DetectEncoding(buf.Bytes())
|
||||
if charsetLabel != "UTF-8" && err == nil {
|
||||
charsetLabel := base.DetectEncoding(buf.Bytes())
|
||||
if charsetLabel != "UTF-8" {
|
||||
encoding, _ := charset.Lookup(charsetLabel)
|
||||
if encoding != nil {
|
||||
d := encoding.NewDecoder()
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/smtp"
|
||||
"net/textproto"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -26,12 +27,12 @@ type LoginType int
|
||||
|
||||
// Note: new type must be added at the end of list to maintain compatibility.
|
||||
const (
|
||||
NOTYPE LoginType = iota
|
||||
PLAIN
|
||||
LDAP
|
||||
SMTP
|
||||
PAM
|
||||
DLDAP
|
||||
LOGIN_NOTYPE LoginType = iota
|
||||
LOGIN_PLAIN
|
||||
LOGIN_LDAP
|
||||
LOGIN_SMTP
|
||||
LOGIN_PAM
|
||||
LOGIN_DLDAP
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -40,10 +41,10 @@ var (
|
||||
)
|
||||
|
||||
var LoginNames = map[LoginType]string{
|
||||
LDAP: "LDAP (via BindDN)",
|
||||
DLDAP: "LDAP (simple auth)",
|
||||
SMTP: "SMTP",
|
||||
PAM: "PAM",
|
||||
LOGIN_LDAP: "LDAP (via BindDN)",
|
||||
LOGIN_DLDAP: "LDAP (simple auth)",
|
||||
LOGIN_SMTP: "SMTP",
|
||||
LOGIN_PAM: "PAM",
|
||||
}
|
||||
|
||||
// Ensure structs implemented interface.
|
||||
@@ -108,11 +109,11 @@ func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) {
|
||||
switch colName {
|
||||
case "type":
|
||||
switch LoginType((*val).(int64)) {
|
||||
case LDAP, DLDAP:
|
||||
case LOGIN_LDAP, LOGIN_DLDAP:
|
||||
source.Cfg = new(LDAPConfig)
|
||||
case SMTP:
|
||||
case LOGIN_SMTP:
|
||||
source.Cfg = new(SMTPConfig)
|
||||
case PAM:
|
||||
case LOGIN_PAM:
|
||||
source.Cfg = new(PAMConfig)
|
||||
default:
|
||||
panic("unrecognized login source type: " + com.ToStr(*val))
|
||||
@@ -125,26 +126,26 @@ func (source *LoginSource) TypeName() string {
|
||||
}
|
||||
|
||||
func (source *LoginSource) IsLDAP() bool {
|
||||
return source.Type == LDAP
|
||||
return source.Type == LOGIN_LDAP
|
||||
}
|
||||
|
||||
func (source *LoginSource) IsDLDAP() bool {
|
||||
return source.Type == DLDAP
|
||||
return source.Type == LOGIN_DLDAP
|
||||
}
|
||||
|
||||
func (source *LoginSource) IsSMTP() bool {
|
||||
return source.Type == SMTP
|
||||
return source.Type == LOGIN_SMTP
|
||||
}
|
||||
|
||||
func (source *LoginSource) IsPAM() bool {
|
||||
return source.Type == PAM
|
||||
return source.Type == LOGIN_PAM
|
||||
}
|
||||
|
||||
func (source *LoginSource) UseTLS() bool {
|
||||
switch source.Type {
|
||||
case LDAP, DLDAP:
|
||||
case LOGIN_LDAP, LOGIN_DLDAP:
|
||||
return source.LDAP().UseSSL
|
||||
case SMTP:
|
||||
case LOGIN_SMTP:
|
||||
return source.SMTP().TLS
|
||||
}
|
||||
|
||||
@@ -153,9 +154,9 @@ func (source *LoginSource) UseTLS() bool {
|
||||
|
||||
func (source *LoginSource) SkipVerify() bool {
|
||||
switch source.Type {
|
||||
case LDAP, DLDAP:
|
||||
case LOGIN_LDAP, LOGIN_DLDAP:
|
||||
return source.LDAP().SkipVerify
|
||||
case SMTP:
|
||||
case LOGIN_SMTP:
|
||||
return source.SMTP().SkipVerify
|
||||
}
|
||||
|
||||
@@ -230,7 +231,7 @@ func DeleteSource(source *LoginSource) error {
|
||||
// It returns the same LoginUserPlain semantic.
|
||||
func LoginUserLDAPSource(u *User, loginName, passwd string, source *LoginSource, autoRegister bool) (*User, error) {
|
||||
cfg := source.Cfg.(*LDAPConfig)
|
||||
directBind := (source.Type == DLDAP)
|
||||
directBind := (source.Type == LOGIN_DLDAP)
|
||||
name, fn, sn, mail, admin, logged := cfg.SearchEntry(loginName, passwd, directBind)
|
||||
if !logged {
|
||||
// User not in LDAP, do nothing
|
||||
@@ -350,7 +351,7 @@ func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error {
|
||||
// Query if name/passwd can login against the LDAP directory pool
|
||||
// Create a local user if success
|
||||
// Return the same LoginUserPlain semantic
|
||||
func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTPConfig, autoRegister bool) (*User, error) {
|
||||
func LoginUserSMTPSource(u *User, name, passwd string, sourceID int64, cfg *SMTPConfig, autoRegister bool) (*User, error) {
|
||||
// Verify allowed domains.
|
||||
if len(cfg.AllowedDomains) > 0 {
|
||||
idx := strings.Index(name, "@")
|
||||
@@ -371,7 +372,11 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP
|
||||
}
|
||||
|
||||
if err := SMTPAuth(auth, cfg); err != nil {
|
||||
if strings.Contains(err.Error(), "Username and Password not accepted") {
|
||||
// Check standard error format first,
|
||||
// then fallback to worse case.
|
||||
tperr, ok := err.(*textproto.Error)
|
||||
if (ok && tperr.Code == 535) ||
|
||||
strings.Contains(err.Error(), "Username and Password not accepted") {
|
||||
return nil, ErrUserNotExist{0, name}
|
||||
}
|
||||
return nil, err
|
||||
@@ -390,8 +395,8 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP
|
||||
u = &User{
|
||||
LowerName: strings.ToLower(loginName),
|
||||
Name: strings.ToLower(loginName),
|
||||
LoginType: SMTP,
|
||||
LoginSource: sourceId,
|
||||
LoginType: LOGIN_SMTP,
|
||||
LoginSource: sourceID,
|
||||
LoginName: name,
|
||||
IsActive: true,
|
||||
Passwd: passwd,
|
||||
@@ -411,7 +416,7 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP
|
||||
// Query if name/passwd can login against PAM
|
||||
// Create a local user if success
|
||||
// Return the same LoginUserPlain semantic
|
||||
func LoginUserPAMSource(u *User, name, passwd string, sourceId int64, cfg *PAMConfig, autoRegister bool) (*User, error) {
|
||||
func LoginUserPAMSource(u *User, name, passwd string, sourceID int64, cfg *PAMConfig, autoRegister bool) (*User, error) {
|
||||
if err := pam.PAMAuth(cfg.ServiceName, name, passwd); err != nil {
|
||||
if strings.Contains(err.Error(), "Authentication failure") {
|
||||
return nil, ErrUserNotExist{0, name}
|
||||
@@ -427,8 +432,8 @@ func LoginUserPAMSource(u *User, name, passwd string, sourceId int64, cfg *PAMCo
|
||||
u = &User{
|
||||
LowerName: strings.ToLower(name),
|
||||
Name: name,
|
||||
LoginType: PAM,
|
||||
LoginSource: sourceId,
|
||||
LoginType: LOGIN_PAM,
|
||||
LoginSource: sourceID,
|
||||
LoginName: name,
|
||||
IsActive: true,
|
||||
Passwd: passwd,
|
||||
@@ -443,11 +448,11 @@ func ExternalUserLogin(u *User, name, passwd string, source *LoginSource, autoRe
|
||||
}
|
||||
|
||||
switch source.Type {
|
||||
case LDAP, DLDAP:
|
||||
case LOGIN_LDAP, LOGIN_DLDAP:
|
||||
return LoginUserLDAPSource(u, name, passwd, source, autoRegister)
|
||||
case SMTP:
|
||||
case LOGIN_SMTP:
|
||||
return LoginUserSMTPSource(u, name, passwd, source.ID, source.Cfg.(*SMTPConfig), autoRegister)
|
||||
case PAM:
|
||||
case LOGIN_PAM:
|
||||
return LoginUserPAMSource(u, name, passwd, source.ID, source.Cfg.(*PAMConfig), autoRegister)
|
||||
}
|
||||
|
||||
@@ -470,7 +475,7 @@ func UserSignIn(uname, passwd string) (*User, error) {
|
||||
|
||||
if userExists {
|
||||
switch u.LoginType {
|
||||
case NOTYPE, PLAIN:
|
||||
case LOGIN_NOTYPE, LOGIN_PLAIN:
|
||||
if u.ValidatePassword(passwd) {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
@@ -13,18 +13,18 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/xorm"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
gouuid "github.com/gogits/gogs/modules/uuid"
|
||||
)
|
||||
|
||||
const _MIN_DB_VER = 0
|
||||
const _MIN_DB_VER = 4
|
||||
|
||||
type Migration interface {
|
||||
Description() string
|
||||
@@ -58,16 +58,13 @@ type Version struct {
|
||||
// If you want to "retire" a migration, remove it from the top of the list and
|
||||
// update _MIN_VER_DB accordingly
|
||||
var migrations = []Migration{
|
||||
NewMigration("generate collaboration from access", accessToCollaboration), // V0 -> V1:v0.5.13
|
||||
NewMigration("make authorize 4 if team is owners", ownerTeamUpdate), // V1 -> V2:v0.5.13
|
||||
NewMigration("refactor access table to use id's", accessRefactor), // V2 -> V3:v0.5.13
|
||||
NewMigration("generate team-repo from team", teamToTeamRepo), // V3 -> V4:v0.5.13
|
||||
NewMigration("fix locale file load panic", fixLocaleFileLoadPanic), // V4 -> V5:v0.6.0
|
||||
NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix), // V5 -> V6:v0.6.3
|
||||
NewMigration("generate issue-label from issue", issueToIssueLabel), // V6 -> V7:v0.6.4
|
||||
NewMigration("refactor attachment table", attachmentRefactor), // V7 -> V8:v0.6.4
|
||||
NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16
|
||||
NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20
|
||||
NewMigration("fix locale file load panic", fixLocaleFileLoadPanic), // V4 -> V5:v0.6.0
|
||||
NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix), // V5 -> V6:v0.6.3
|
||||
NewMigration("generate issue-label from issue", issueToIssueLabel), // V6 -> V7:v0.6.4
|
||||
NewMigration("refactor attachment table", attachmentRefactor), // V7 -> V8:v0.6.4
|
||||
NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16
|
||||
NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20
|
||||
NewMigration("generate rands and salt for organizations", generateOrgRandsAndSalt), // V10 -> V11:v0.8.5
|
||||
}
|
||||
|
||||
// Migrate database to current version
|
||||
@@ -81,24 +78,9 @@ func Migrate(x *xorm.Engine) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("get: %v", err)
|
||||
} else if !has {
|
||||
// If the user table does not exist it is a fresh installation and we
|
||||
// can skip all migrations.
|
||||
needsMigration, err := x.IsTableExist("user")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if needsMigration {
|
||||
isEmpty, err := x.IsTableEmpty("user")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// If the user table is empty it is a fresh installation and we can
|
||||
// skip all migrations.
|
||||
needsMigration = !isEmpty
|
||||
}
|
||||
if !needsMigration {
|
||||
currentVersion.Version = int64(_MIN_DB_VER + len(migrations))
|
||||
}
|
||||
// If the version record does not exist we think
|
||||
// it is a fresh installation and we can skip all migrations.
|
||||
currentVersion.Version = int64(_MIN_DB_VER + len(migrations))
|
||||
|
||||
if _, err = x.InsertOne(currentVersion); err != nil {
|
||||
return fmt.Errorf("insert: %v", err)
|
||||
@@ -107,7 +89,8 @@ func Migrate(x *xorm.Engine) error {
|
||||
|
||||
v := currentVersion.Version
|
||||
if _MIN_DB_VER > v {
|
||||
log.Fatal(4, "Gogs no longer supports auto-migration from your previously installed version. Please try to upgrade to a lower version first, then upgrade to current version.")
|
||||
log.Fatal(4, `Gogs no longer supports auto-migration from your previously installed version.
|
||||
Please try to upgrade to a lower version (>= v0.6.0) first, then upgrade to current version.`)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -137,276 +120,6 @@ func sessionRelease(sess *xorm.Session) {
|
||||
sess.Close()
|
||||
}
|
||||
|
||||
func accessToCollaboration(x *xorm.Engine) (err error) {
|
||||
type Collaboration struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Created time.Time
|
||||
}
|
||||
|
||||
if err = x.Sync(new(Collaboration)); err != nil {
|
||||
return fmt.Errorf("sync: %v", err)
|
||||
}
|
||||
|
||||
results, err := x.Query("SELECT u.id AS `uid`, a.repo_name AS `repo`, a.mode AS `mode`, a.created as `created` FROM `access` a JOIN `user` u ON a.user_name=u.lower_name")
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no such column") {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
offset := strings.Split(time.Now().String(), " ")[2]
|
||||
for _, result := range results {
|
||||
mode := com.StrTo(result["mode"]).MustInt64()
|
||||
// Collaborators must have write access.
|
||||
if mode < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
userID := com.StrTo(result["uid"]).MustInt64()
|
||||
repoRefName := string(result["repo"])
|
||||
|
||||
var created time.Time
|
||||
switch {
|
||||
case setting.UseSQLite3:
|
||||
created, _ = time.Parse(time.RFC3339, string(result["created"]))
|
||||
case setting.UseMySQL:
|
||||
created, _ = time.Parse("2006-01-02 15:04:05-0700", string(result["created"])+offset)
|
||||
case setting.UsePostgreSQL:
|
||||
created, _ = time.Parse("2006-01-02T15:04:05Z-0700", string(result["created"])+offset)
|
||||
}
|
||||
|
||||
// find owner of repository
|
||||
parts := strings.SplitN(repoRefName, "/", 2)
|
||||
ownerName := parts[0]
|
||||
repoName := parts[1]
|
||||
|
||||
results, err := sess.Query("SELECT u.id as `uid`, ou.uid as `memberid` FROM `user` u LEFT JOIN org_user ou ON ou.org_id=u.id WHERE u.lower_name=?", ownerName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(results) < 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
ownerID := com.StrTo(results[0]["uid"]).MustInt64()
|
||||
if ownerID == userID {
|
||||
continue
|
||||
}
|
||||
|
||||
// test if user is member of owning organization
|
||||
isMember := false
|
||||
for _, member := range results {
|
||||
memberID := com.StrTo(member["memberid"]).MustInt64()
|
||||
// We can skip all cases that a user is member of the owning organization
|
||||
if memberID == userID {
|
||||
isMember = true
|
||||
}
|
||||
}
|
||||
if isMember {
|
||||
continue
|
||||
}
|
||||
|
||||
results, err = sess.Query("SELECT id FROM `repository` WHERE owner_id=? AND lower_name=?", ownerID, repoName)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(results) < 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
collaboration := &Collaboration{
|
||||
UserID: userID,
|
||||
RepoID: com.StrTo(results[0]["id"]).MustInt64(),
|
||||
}
|
||||
has, err := sess.Get(collaboration)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if has {
|
||||
continue
|
||||
}
|
||||
|
||||
collaboration.Created = created
|
||||
if _, err = sess.InsertOne(collaboration); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func ownerTeamUpdate(x *xorm.Engine) (err error) {
|
||||
if _, err := x.Exec("UPDATE `team` SET authorize=4 WHERE lower_name=?", "owners"); err != nil {
|
||||
return fmt.Errorf("update owner team table: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func accessRefactor(x *xorm.Engine) (err error) {
|
||||
type (
|
||||
AccessMode int
|
||||
Access struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"UNIQUE(s)"`
|
||||
RepoID int64 `xorm:"UNIQUE(s)"`
|
||||
Mode AccessMode
|
||||
}
|
||||
UserRepo struct {
|
||||
UserID int64
|
||||
RepoID int64
|
||||
}
|
||||
)
|
||||
|
||||
// We consiously don't start a session yet as we make only reads for now, no writes
|
||||
|
||||
accessMap := make(map[UserRepo]AccessMode, 50)
|
||||
|
||||
results, err := x.Query("SELECT r.id AS `repo_id`, r.is_private AS `is_private`, r.owner_id AS `owner_id`, u.type AS `owner_type` FROM `repository` r LEFT JOIN `user` u ON r.owner_id=u.id")
|
||||
if err != nil {
|
||||
return fmt.Errorf("select repositories: %v", err)
|
||||
}
|
||||
for _, repo := range results {
|
||||
repoID := com.StrTo(repo["repo_id"]).MustInt64()
|
||||
isPrivate := com.StrTo(repo["is_private"]).MustInt() > 0
|
||||
ownerID := com.StrTo(repo["owner_id"]).MustInt64()
|
||||
ownerIsOrganization := com.StrTo(repo["owner_type"]).MustInt() > 0
|
||||
|
||||
results, err := x.Query("SELECT `user_id` FROM `collaboration` WHERE repo_id=?", repoID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("select collaborators: %v", err)
|
||||
}
|
||||
for _, user := range results {
|
||||
userID := com.StrTo(user["user_id"]).MustInt64()
|
||||
accessMap[UserRepo{userID, repoID}] = 2 // WRITE ACCESS
|
||||
}
|
||||
|
||||
if !ownerIsOrganization {
|
||||
continue
|
||||
}
|
||||
|
||||
// The minimum level to add a new access record,
|
||||
// because public repository has implicit open access.
|
||||
minAccessLevel := AccessMode(0)
|
||||
if !isPrivate {
|
||||
minAccessLevel = 1
|
||||
}
|
||||
|
||||
repoString := "$" + string(repo["repo_id"]) + "|"
|
||||
|
||||
results, err = x.Query("SELECT `id`,`authorize`,`repo_ids` FROM `team` WHERE org_id=? AND authorize>? ORDER BY `authorize` ASC", ownerID, int(minAccessLevel))
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no such column") {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("select teams from org: %v", err)
|
||||
}
|
||||
|
||||
for _, team := range results {
|
||||
if !strings.Contains(string(team["repo_ids"]), repoString) {
|
||||
continue
|
||||
}
|
||||
teamID := com.StrTo(team["id"]).MustInt64()
|
||||
mode := AccessMode(com.StrTo(team["authorize"]).MustInt())
|
||||
|
||||
results, err := x.Query("SELECT `uid` FROM `team_user` WHERE team_id=?", teamID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("select users from team: %v", err)
|
||||
}
|
||||
for _, user := range results {
|
||||
userID := com.StrTo(user["uid"]).MustInt64()
|
||||
accessMap[UserRepo{userID, repoID}] = mode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Drop table can't be in a session (at least not in sqlite)
|
||||
if _, err = x.Exec("DROP TABLE `access`"); err != nil {
|
||||
return fmt.Errorf("drop access table: %v", err)
|
||||
}
|
||||
|
||||
// Now we start writing so we make a session
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = sess.Sync2(new(Access)); err != nil {
|
||||
return fmt.Errorf("sync: %v", err)
|
||||
}
|
||||
|
||||
accesses := make([]*Access, 0, len(accessMap))
|
||||
for ur, mode := range accessMap {
|
||||
accesses = append(accesses, &Access{UserID: ur.UserID, RepoID: ur.RepoID, Mode: mode})
|
||||
}
|
||||
|
||||
if _, err = sess.Insert(accesses); err != nil {
|
||||
return fmt.Errorf("insert accesses: %v", err)
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func teamToTeamRepo(x *xorm.Engine) error {
|
||||
type TeamRepo struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OrgID int64 `xorm:"INDEX"`
|
||||
TeamID int64 `xorm:"UNIQUE(s)"`
|
||||
RepoID int64 `xorm:"UNIQUE(s)"`
|
||||
}
|
||||
|
||||
teamRepos := make([]*TeamRepo, 0, 50)
|
||||
|
||||
results, err := x.Query("SELECT `id`,`org_id`,`repo_ids` FROM `team`")
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no such column") {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("select teams: %v", err)
|
||||
}
|
||||
for _, team := range results {
|
||||
orgID := com.StrTo(team["org_id"]).MustInt64()
|
||||
teamID := com.StrTo(team["id"]).MustInt64()
|
||||
|
||||
// #1032: legacy code can have duplicated IDs for same repository.
|
||||
mark := make(map[int64]bool)
|
||||
for _, idStr := range strings.Split(string(team["repo_ids"]), "|") {
|
||||
repoID := com.StrTo(strings.TrimPrefix(idStr, "$")).MustInt64()
|
||||
if repoID == 0 || mark[repoID] {
|
||||
continue
|
||||
}
|
||||
|
||||
mark[repoID] = true
|
||||
teamRepos = append(teamRepos, &TeamRepo{
|
||||
OrgID: orgID,
|
||||
TeamID: teamID,
|
||||
RepoID: repoID,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = sess.Sync2(new(TeamRepo)); err != nil {
|
||||
return fmt.Errorf("sync2: %v", err)
|
||||
} else if _, err = sess.Insert(teamRepos); err != nil {
|
||||
return fmt.Errorf("insert team-repos: %v", err)
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func fixLocaleFileLoadPanic(_ *xorm.Engine) error {
|
||||
cfg, err := ini.Load(setting.CustomConf)
|
||||
if err != nil {
|
||||
@@ -494,7 +207,8 @@ func issueToIssueLabel(x *xorm.Engine) error {
|
||||
issueLabels := make([]*IssueLabel, 0, 50)
|
||||
results, err := x.Query("SELECT `id`,`label_ids` FROM `issue`")
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no such column") {
|
||||
if strings.Contains(err.Error(), "no such column") ||
|
||||
strings.Contains(err.Error(), "Unknown column") {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("select issues: %v", err)
|
||||
@@ -653,6 +367,9 @@ func renamePullRequestFields(x *xorm.Engine) (err error) {
|
||||
Index: com.StrTo(pr["pull_index"]).MustInt64(),
|
||||
HeadBranch: string(pr["head_barcnh"]),
|
||||
}
|
||||
if pull.Index == 0 {
|
||||
continue
|
||||
}
|
||||
if _, err = sess.Id(pull.ID).Update(pull); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -707,3 +424,32 @@ func cleanUpMigrateRepoInfo(x *xorm.Engine) (err error) {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateOrgRandsAndSalt(x *xorm.Engine) (err error) {
|
||||
type User struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Rands string `xorm:"VARCHAR(10)"`
|
||||
Salt string `xorm:"VARCHAR(10)"`
|
||||
}
|
||||
|
||||
orgs := make([]*User, 0, 10)
|
||||
if err = x.Where("type=1").And("rands=''").Find(&orgs); err != nil {
|
||||
return fmt.Errorf("select all organizations: %v", err)
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, org := range orgs {
|
||||
org.Rands = base.GetRandomString(10)
|
||||
org.Salt = base.GetRandomString(10)
|
||||
if _, err = sess.Id(org.ID).Update(org); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
@@ -108,7 +108,10 @@ func CreateOrganization(org, owner *User) (err error) {
|
||||
|
||||
org.LowerName = strings.ToLower(org.Name)
|
||||
org.FullName = org.Name
|
||||
org.Rands = GetUserSalt()
|
||||
org.Salt = GetUserSalt()
|
||||
org.UseCustomAvatar = true
|
||||
org.MaxRepoCreation = -1
|
||||
org.NumTeams = 1
|
||||
org.NumMembers = 1
|
||||
|
||||
@@ -271,10 +274,15 @@ func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
|
||||
return getOwnedOrgsByUserID(sess.Desc(desc), userID)
|
||||
}
|
||||
|
||||
// GetOrgUsersByUserId returns all organization-user relations by user ID.
|
||||
func GetOrgUsersByUserId(uid int64) ([]*OrgUser, error) {
|
||||
// GetOrgUsersByUserID returns all organization-user relations by user ID.
|
||||
func GetOrgUsersByUserID(uid int64, all bool) ([]*OrgUser, error) {
|
||||
ous := make([]*OrgUser, 0, 10)
|
||||
err := x.Where("uid=?", uid).Find(&ous)
|
||||
sess := x.Where("uid=?", uid)
|
||||
if !all {
|
||||
// Only show public organizations
|
||||
sess.And("is_public=?", true)
|
||||
}
|
||||
err := sess.Find(&ous)
|
||||
return ous, err
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ import (
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/xorm"
|
||||
|
||||
"github.com/gogits/gogs/modules/git"
|
||||
"github.com/gogits/git-module"
|
||||
api "github.com/gogits/go-gogs-client"
|
||||
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/process"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
@@ -124,6 +126,12 @@ func (pr *PullRequest) CanAutoMerge() bool {
|
||||
|
||||
// Merge merges pull request to base repository.
|
||||
func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error) {
|
||||
if err = pr.GetHeadRepo(); err != nil {
|
||||
return fmt.Errorf("GetHeadRepo: %v", err)
|
||||
} else if err = pr.GetBaseRepo(); err != nil {
|
||||
return fmt.Errorf("GetBaseRepo: %v", err)
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
@@ -134,18 +142,14 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
||||
return fmt.Errorf("Issue.changeStatus: %v", err)
|
||||
}
|
||||
|
||||
if err = pr.getHeadRepo(sess); err != nil {
|
||||
return fmt.Errorf("getHeadRepo: %v", err)
|
||||
}
|
||||
|
||||
headRepoPath := RepoPath(pr.HeadUserName, pr.HeadRepo.Name)
|
||||
headGitRepo, err := git.OpenRepository(headRepoPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("OpenRepository: %v", err)
|
||||
}
|
||||
pr.MergedCommitID, err = headGitRepo.GetCommitIdOfBranch(pr.HeadBranch)
|
||||
pr.MergedCommitID, err = headGitRepo.GetBranchCommitID(pr.HeadBranch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetCommitIdOfBranch: %v", err)
|
||||
return fmt.Errorf("GetBranchCommitID: %v", err)
|
||||
}
|
||||
|
||||
if err = mergePullRequestAction(sess, doer, pr.Issue.Repo, pr.Issue); err != nil {
|
||||
@@ -213,7 +217,38 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
||||
return fmt.Errorf("git push: %s", stderr)
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
if err = sess.Commit(); err != nil {
|
||||
return fmt.Errorf("Commit: %v", err)
|
||||
}
|
||||
|
||||
// Compose commit repository action
|
||||
l, err := headGitRepo.CommitsBetweenIDs(pr.MergedCommitID, pr.MergeBase)
|
||||
if err != nil {
|
||||
return fmt.Errorf("CommitsBetween: %v", err)
|
||||
}
|
||||
p := &api.PushPayload{
|
||||
Ref: "refs/heads/" + pr.BaseBranch,
|
||||
Before: pr.MergeBase,
|
||||
After: pr.MergedCommitID,
|
||||
CompareUrl: setting.AppUrl + pr.BaseRepo.ComposeCompareURL(pr.MergeBase, pr.MergedCommitID),
|
||||
Commits: ListToPushCommits(l).ToApiPayloadCommits(pr.BaseRepo.FullRepoLink()),
|
||||
Repo: pr.BaseRepo.ComposePayload(),
|
||||
Pusher: &api.PayloadAuthor{
|
||||
Name: pr.HeadRepo.MustOwner().DisplayName(),
|
||||
Email: pr.HeadRepo.MustOwner().Email,
|
||||
UserName: pr.HeadRepo.MustOwner().Name,
|
||||
},
|
||||
Sender: &api.PayloadUser{
|
||||
UserName: doer.Name,
|
||||
ID: doer.Id,
|
||||
AvatarUrl: setting.AppUrl + doer.RelAvatarLink(),
|
||||
},
|
||||
}
|
||||
if err = PrepareWebhooks(pr.BaseRepo, HOOK_EVENT_PUSH, p); err != nil {
|
||||
return fmt.Errorf("PrepareWebhooks: %v", err)
|
||||
}
|
||||
go HookQueue.Add(pr.BaseRepo.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// patchConflicts is a list of conflit description from Git.
|
||||
@@ -411,8 +446,6 @@ func (pr *PullRequest) UpdatePatch() (err error) {
|
||||
|
||||
if err = pr.GetBaseRepo(); err != nil {
|
||||
return fmt.Errorf("GetBaseRepo: %v", err)
|
||||
} else if err = pr.BaseRepo.GetOwner(); err != nil {
|
||||
return fmt.Errorf("GetOwner: %v", err)
|
||||
}
|
||||
|
||||
headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
|
||||
@@ -422,7 +455,7 @@ func (pr *PullRequest) UpdatePatch() (err error) {
|
||||
|
||||
// Add a temporary remote.
|
||||
tmpRemote := com.ToStr(time.Now().UnixNano())
|
||||
if err = headGitRepo.AddRemote(tmpRemote, RepoPath(pr.BaseRepo.Owner.Name, pr.BaseRepo.Name)); err != nil {
|
||||
if err = headGitRepo.AddRemote(tmpRemote, RepoPath(pr.BaseRepo.MustOwner().Name, pr.BaseRepo.Name), true); err != nil {
|
||||
return fmt.Errorf("AddRemote: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
|
||||
@@ -12,7 +12,8 @@ import (
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
|
||||
"github.com/gogits/gogs/modules/git"
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/modules/process"
|
||||
)
|
||||
|
||||
@@ -27,8 +28,8 @@ type Release struct {
|
||||
Target string
|
||||
Title string
|
||||
Sha1 string `xorm:"VARCHAR(40)"`
|
||||
NumCommits int
|
||||
NumCommitsBehind int `xorm:"-"`
|
||||
NumCommits int64
|
||||
NumCommitsBehind int64 `xorm:"-"`
|
||||
Note string `xorm:"TEXT"`
|
||||
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
|
||||
IsPrerelease bool
|
||||
@@ -51,31 +52,27 @@ func IsReleaseExist(repoID int64, tagName string) (bool, error) {
|
||||
return x.Get(&Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)})
|
||||
}
|
||||
|
||||
func init() {
|
||||
git.GetVersion()
|
||||
}
|
||||
|
||||
func createTag(gitRepo *git.Repository, rel *Release) error {
|
||||
// Only actual create when publish.
|
||||
if !rel.IsDraft {
|
||||
if !gitRepo.IsTagExist(rel.TagName) {
|
||||
commit, err := gitRepo.GetCommitOfBranch(rel.Target)
|
||||
commit, err := gitRepo.GetBranchCommit(rel.Target)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("GetBranchCommit: %v", err)
|
||||
}
|
||||
|
||||
if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
commit, err := gitRepo.GetCommitOfTag(rel.TagName)
|
||||
commit, err := gitRepo.GetTagCommit(rel.TagName)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("GetTagCommit: %v", err)
|
||||
}
|
||||
|
||||
rel.NumCommits, err = commit.CommitsCount()
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("CommitsCount: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
184
models/repo.go
184
models/repo.go
@@ -27,7 +27,7 @@ import (
|
||||
"github.com/mcuadros/go-version"
|
||||
"gopkg.in/ini.v1"
|
||||
|
||||
"github.com/gogits/git-shell"
|
||||
"github.com/gogits/git-module"
|
||||
api "github.com/gogits/go-gogs-client"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
@@ -98,7 +98,7 @@ func NewRepoContext() {
|
||||
}
|
||||
|
||||
// Check Git version.
|
||||
gitVer, err := git.Version()
|
||||
gitVer, err := git.BinVersion()
|
||||
if err != nil {
|
||||
log.Fatal(4, "Fail to get Git version: %v", err)
|
||||
}
|
||||
@@ -129,6 +129,8 @@ func NewRepoContext() {
|
||||
log.Fatal(4, "Fail to execute 'git config --global core.quotepath false': %s", stderr)
|
||||
}
|
||||
|
||||
// Clean up temporary data.
|
||||
os.RemoveAll(filepath.Join(setting.AppDataPath, "tmp"))
|
||||
}
|
||||
|
||||
// Repository represents a git repository.
|
||||
@@ -164,6 +166,8 @@ type Repository struct {
|
||||
|
||||
// Advanced settings
|
||||
EnableWiki bool `xorm:"NOT NULL DEFAULT true"`
|
||||
EnableExternalWiki bool
|
||||
ExternalWikiURL string
|
||||
EnableIssues bool `xorm:"NOT NULL DEFAULT true"`
|
||||
EnableExternalTracker bool
|
||||
ExternalTrackerFormat string
|
||||
@@ -301,10 +305,22 @@ func (repo *Repository) RepoPath() string {
|
||||
return repo.repoPath(x)
|
||||
}
|
||||
|
||||
func (repo *Repository) GitConfigPath() string {
|
||||
return filepath.Join(repo.RepoPath(), "config")
|
||||
}
|
||||
|
||||
func (repo *Repository) RepoLink() string {
|
||||
return setting.AppSubUrl + "/" + repo.MustOwner().Name + "/" + repo.Name
|
||||
}
|
||||
|
||||
func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) string {
|
||||
return fmt.Sprintf("%s/%s/compare/%s...%s", repo.MustOwner().Name, repo.Name, oldCommitID, newCommitID)
|
||||
}
|
||||
|
||||
func (repo *Repository) FullRepoLink() string {
|
||||
return setting.AppUrl + repo.MustOwner().Name + "/" + repo.Name
|
||||
}
|
||||
|
||||
func (repo *Repository) HasAccess(u *User) bool {
|
||||
has, _ := HasAccess(u, repo, ACCESS_MODE_READ)
|
||||
return has
|
||||
@@ -341,7 +357,7 @@ func (repo *Repository) LocalCopyPath() string {
|
||||
|
||||
func updateLocalCopy(repoPath, localPath string) error {
|
||||
if !com.IsExist(localPath) {
|
||||
if err := git.Clone(repoPath, localPath); err != nil {
|
||||
if err := git.Clone(repoPath, localPath, git.CloneRepoOptions{}); err != nil {
|
||||
return fmt.Errorf("Clone: %v", err)
|
||||
}
|
||||
} else {
|
||||
@@ -387,7 +403,7 @@ func (repo *Repository) ComposePayload() *api.PayloadRepo {
|
||||
return &api.PayloadRepo{
|
||||
ID: repo.ID,
|
||||
Name: repo.LowerName,
|
||||
URL: repo.RepoLink(),
|
||||
URL: repo.FullRepoLink(),
|
||||
SSHURL: cl.SSH,
|
||||
CloneURL: cl.HTTPS,
|
||||
Description: repo.Description,
|
||||
@@ -480,6 +496,8 @@ type Mirror struct {
|
||||
Interval int // Hour.
|
||||
Updated time.Time `xorm:"UPDATED"`
|
||||
NextUpdate time.Time
|
||||
|
||||
address string `xorm:"-"`
|
||||
}
|
||||
|
||||
func (m *Mirror) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -493,6 +511,61 @@ func (m *Mirror) AfterSet(colName string, _ xorm.Cell) {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Mirror) readAddress() {
|
||||
if len(m.address) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
cfg, err := ini.Load(m.Repo.GitConfigPath())
|
||||
if err != nil {
|
||||
log.Error(4, "Load: %v", err)
|
||||
return
|
||||
}
|
||||
m.address = cfg.Section("remote \"origin\"").Key("url").Value()
|
||||
}
|
||||
|
||||
// HandleCloneUserCredentials replaces user credentials from HTTP/HTTPS URL
|
||||
// with placeholder <credentials>.
|
||||
// It will fail for any other forms of clone addresses.
|
||||
func HandleCloneUserCredentials(url string, mosaics bool) string {
|
||||
i := strings.Index(url, "@")
|
||||
if i == -1 {
|
||||
return url
|
||||
}
|
||||
start := strings.Index(url, "://")
|
||||
if start == -1 {
|
||||
return url
|
||||
}
|
||||
if mosaics {
|
||||
return url[:start+3] + "<credentials>" + url[i:]
|
||||
}
|
||||
return url[:start+3] + url[i+1:]
|
||||
}
|
||||
|
||||
// Address returns mirror address from Git repository config without credentials.
|
||||
func (m *Mirror) Address() string {
|
||||
m.readAddress()
|
||||
return HandleCloneUserCredentials(m.address, false)
|
||||
}
|
||||
|
||||
// FullAddress returns mirror address from Git repository config.
|
||||
func (m *Mirror) FullAddress() string {
|
||||
m.readAddress()
|
||||
return m.address
|
||||
}
|
||||
|
||||
// SaveAddress writes new address to Git repository config.
|
||||
func (m *Mirror) SaveAddress(addr string) error {
|
||||
configPath := m.Repo.GitConfigPath()
|
||||
cfg, err := ini.Load(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Load: %v", err)
|
||||
}
|
||||
|
||||
cfg.Section("remote \"origin\"").Key("url").SetValue(addr)
|
||||
return cfg.SaveToIndent(configPath, "\t")
|
||||
}
|
||||
|
||||
func getMirror(e Engine, repoId int64) (*Mirror, error) {
|
||||
m := &Mirror{RepoID: repoId}
|
||||
has, err := e.Get(m)
|
||||
@@ -523,25 +596,6 @@ func createUpdateHook(repoPath string) error {
|
||||
fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+setting.AppPath+"\"", setting.CustomConf))
|
||||
}
|
||||
|
||||
// MirrorRepository creates a mirror repository from source.
|
||||
func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error {
|
||||
_, stderr, err := process.ExecTimeout(10*time.Minute,
|
||||
fmt.Sprintf("MirrorRepository: %s/%s", userName, repoName),
|
||||
"git", "clone", "--mirror", url, repoPath)
|
||||
if err != nil {
|
||||
return errors.New("git clone --mirror: " + stderr)
|
||||
}
|
||||
|
||||
if _, err = x.InsertOne(&Mirror{
|
||||
RepoID: repoId,
|
||||
Interval: 24,
|
||||
NextUpdate: time.Now().Add(24 * time.Hour),
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type MigrateRepoOptions struct {
|
||||
Name string
|
||||
Description string
|
||||
@@ -578,29 +632,35 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
||||
repo.NumWatches = 1
|
||||
}
|
||||
|
||||
repo.IsBare = false
|
||||
if opts.IsMirror {
|
||||
if err = MirrorRepository(repo.ID, u.Name, repo.Name, repoPath, opts.RemoteAddr); err != nil {
|
||||
return repo, err
|
||||
}
|
||||
repo.IsMirror = true
|
||||
return repo, UpdateRepository(repo, false)
|
||||
} else {
|
||||
os.RemoveAll(repoPath)
|
||||
os.RemoveAll(repoPath)
|
||||
if err = git.Clone(opts.RemoteAddr, repoPath, git.CloneRepoOptions{
|
||||
Mirror: true,
|
||||
Quiet: true,
|
||||
Timeout: 10 * time.Minute,
|
||||
}); err != nil {
|
||||
return repo, fmt.Errorf("Clone: %v", err)
|
||||
}
|
||||
|
||||
// FIXME: this command could for both migrate and mirror
|
||||
_, stderr, err := process.ExecTimeout(10*time.Minute,
|
||||
fmt.Sprintf("MigrateRepository: %s", repoPath),
|
||||
"git", "clone", "--mirror", "--bare", "--quiet", opts.RemoteAddr, repoPath)
|
||||
if err != nil {
|
||||
return repo, fmt.Errorf("git clone --mirror --bare --quiet: %v", stderr)
|
||||
} else if err = createUpdateHook(repoPath); err != nil {
|
||||
return repo, fmt.Errorf("create update hook: %v", err)
|
||||
if opts.IsMirror {
|
||||
if _, err = x.InsertOne(&Mirror{
|
||||
RepoID: repo.ID,
|
||||
Interval: 24,
|
||||
NextUpdate: time.Now().Add(24 * time.Hour),
|
||||
}); err != nil {
|
||||
return repo, fmt.Errorf("InsertOne: %v", err)
|
||||
}
|
||||
|
||||
repo.IsMirror = true
|
||||
return repo, UpdateRepository(repo, false)
|
||||
}
|
||||
|
||||
if err = createUpdateHook(repoPath); err != nil {
|
||||
return repo, fmt.Errorf("createUpdateHook: %v", err)
|
||||
}
|
||||
|
||||
// Clean up mirror info which prevents "push --all".
|
||||
configPath := filepath.Join(repoPath, "/config")
|
||||
// This also removes possible user credentials.
|
||||
configPath := repo.GitConfigPath()
|
||||
cfg, err := ini.Load(configPath)
|
||||
if err != nil {
|
||||
return repo, fmt.Errorf("open config file: %v", err)
|
||||
@@ -611,7 +671,7 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
|
||||
}
|
||||
|
||||
// Check if repository is empty.
|
||||
_, stderr, err = com.ExecCmdDir(repoPath, "git", "log", "-1")
|
||||
_, stderr, err := com.ExecCmdDir(repoPath, "git", "log", "-1")
|
||||
if err != nil {
|
||||
if strings.Contains(stderr, "fatal: bad default revision 'HEAD'") {
|
||||
repo.IsBare = true
|
||||
@@ -844,6 +904,10 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
||||
|
||||
// CreateRepository creates a repository for given user or organization.
|
||||
func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error) {
|
||||
if !u.CanCreateRepo() {
|
||||
return nil, ErrReachLimitOfRepo{u.MaxRepoCreation}
|
||||
}
|
||||
|
||||
repo := &Repository{
|
||||
OwnerID: u.Id,
|
||||
Owner: u,
|
||||
@@ -1239,12 +1303,14 @@ func DeleteRepository(uid, repoID int64) error {
|
||||
}
|
||||
}
|
||||
|
||||
wikiPath := repo.WikiPath()
|
||||
if err = os.RemoveAll(wikiPath); err != nil {
|
||||
desc := fmt.Sprintf("delete repository wiki [%s]: %v", wikiPath, err)
|
||||
log.Warn(desc)
|
||||
if err = CreateRepositoryNotice(desc); err != nil {
|
||||
log.Error(4, "CreateRepositoryNotice: %v", err)
|
||||
wikiPaths := []string{repo.WikiPath(), repo.LocalWikiPath()}
|
||||
for _, wikiPath := range wikiPaths {
|
||||
if err = os.RemoveAll(wikiPath); err != nil {
|
||||
desc := fmt.Sprintf("delete repository wiki [%s]: %v", wikiPath, err)
|
||||
log.Warn(desc)
|
||||
if err = CreateRepositoryNotice(desc); err != nil {
|
||||
log.Error(4, "CreateRepositoryNotice: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1531,13 +1597,11 @@ func GitFsck() {
|
||||
|
||||
log.Trace("Doing: GitFsck")
|
||||
|
||||
args := append([]string{"fsck"}, setting.Cron.RepoHealthCheck.Args...)
|
||||
if err := x.Where("id>0").Iterate(new(Repository),
|
||||
func(idx int, bean interface{}) error {
|
||||
repo := bean.(*Repository)
|
||||
repoPath := repo.RepoPath()
|
||||
_, _, err := process.ExecDir(-1, repoPath, "Repository health check", "git", args...)
|
||||
if err != nil {
|
||||
if err := git.Fsck(repoPath, setting.Cron.RepoHealthCheck.Timeout, setting.Cron.RepoHealthCheck.Args...); err != nil {
|
||||
desc := fmt.Sprintf("Fail to health check repository(%s)", repoPath)
|
||||
log.Warn(desc)
|
||||
if err = CreateRepositoryNotice(desc); err != nil {
|
||||
@@ -1826,8 +1890,13 @@ func GetWatchers(repoID int64) ([]*Watch, error) {
|
||||
// Repository.GetWatchers returns range of users watching given repository.
|
||||
func (repo *Repository) GetWatchers(page int) ([]*User, error) {
|
||||
users := make([]*User, 0, ItemsPerPage)
|
||||
return users, x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).
|
||||
Where("repo_id=?", repo.ID).Join("LEFT", "watch", "user.id=watch.user_id").Find(&users)
|
||||
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("watch.repo_id=?", repo.ID)
|
||||
if setting.UsePostgreSQL {
|
||||
sess = sess.Join("LEFT", "watch", `"user".id=watch.user_id`)
|
||||
} else {
|
||||
sess = sess.Join("LEFT", "watch", "user.id=watch.user_id")
|
||||
}
|
||||
return users, sess.Find(&users)
|
||||
}
|
||||
|
||||
func notifyWatchers(e Engine, act *Action) error {
|
||||
@@ -1909,8 +1978,13 @@ func IsStaring(uid, repoId int64) bool {
|
||||
|
||||
func (repo *Repository) GetStargazers(page int) ([]*User, error) {
|
||||
users := make([]*User, 0, ItemsPerPage)
|
||||
return users, x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).
|
||||
Where("repo_id=?", repo.ID).Join("LEFT", "star", "user.id=star.uid").Find(&users)
|
||||
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("star.repo_id=?", repo.ID)
|
||||
if setting.UsePostgreSQL {
|
||||
sess = sess.Join("LEFT", "star", `"user".id=star.uid`)
|
||||
} else {
|
||||
sess = sess.Join("LEFT", "star", "user.id=star.uid")
|
||||
}
|
||||
return users, sess.Find(&users)
|
||||
}
|
||||
|
||||
// ___________ __
|
||||
|
||||
@@ -299,6 +299,11 @@ func addKey(e Engine, key *PublicKey) (err error) {
|
||||
if _, err = e.Insert(key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Don't need to rewrite this file if builtin SSH server is enabled.
|
||||
if setting.StartSSHServer {
|
||||
return nil
|
||||
}
|
||||
return saveAuthorizedKeyFile(key)
|
||||
}
|
||||
|
||||
@@ -439,6 +444,11 @@ func deletePublicKey(e *xorm.Session, keyID int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Don't need to rewrite this file if builtin SSH server is enabled.
|
||||
if setting.StartSSHServer {
|
||||
return nil
|
||||
}
|
||||
|
||||
fpath := filepath.Join(SSHPath, "authorized_keys")
|
||||
tmpPath := filepath.Join(SSHPath, "authorized_keys.tmp")
|
||||
if err = rewriteAuthorizedKeys(key, fpath, tmpPath); err != nil {
|
||||
@@ -10,7 +10,8 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/gogits/gogs/modules/git"
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
)
|
||||
|
||||
@@ -46,6 +47,24 @@ func DeleteUpdateTaskByUUID(uuid string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func ListToPushCommits(l *list.List) *PushCommits {
|
||||
commits := make([]*PushCommit, 0)
|
||||
var actEmail string
|
||||
for e := l.Front(); e != nil; e = e.Next() {
|
||||
commit := e.Value.(*git.Commit)
|
||||
if actEmail == "" {
|
||||
actEmail = commit.Committer.Email
|
||||
}
|
||||
commits = append(commits,
|
||||
&PushCommit{commit.ID.String(),
|
||||
commit.Message(),
|
||||
commit.Author.Email,
|
||||
commit.Author.Name,
|
||||
})
|
||||
}
|
||||
return &PushCommits{l.Len(), commits, "", nil}
|
||||
}
|
||||
|
||||
func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName string, userID int64) error {
|
||||
isNew := strings.HasPrefix(oldCommitID, "0000000")
|
||||
if isNew &&
|
||||
@@ -116,7 +135,7 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName
|
||||
// Push new branch.
|
||||
var l *list.List
|
||||
if isNew {
|
||||
l, err = newCommit.CommitsBefore()
|
||||
l, err = newCommit.CommitsBeforeLimit(10)
|
||||
if err != nil {
|
||||
return fmt.Errorf("CommitsBefore: %v", err)
|
||||
}
|
||||
@@ -131,24 +150,8 @@ func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName
|
||||
return fmt.Errorf("runUpdate.Commit repoId: %v", err)
|
||||
}
|
||||
|
||||
// Push commits.
|
||||
commits := make([]*PushCommit, 0)
|
||||
var actEmail string
|
||||
for e := l.Front(); e != nil; e = e.Next() {
|
||||
commit := e.Value.(*git.Commit)
|
||||
if actEmail == "" {
|
||||
actEmail = commit.Committer.Email
|
||||
}
|
||||
commits = append(commits,
|
||||
&PushCommit{commit.ID.String(),
|
||||
commit.Message(),
|
||||
commit.Author.Email,
|
||||
commit.Author.Name,
|
||||
})
|
||||
}
|
||||
|
||||
if err = CommitRepoAction(userID, user.Id, userName, actEmail,
|
||||
repo.ID, repoUserName, repoName, refName, &PushCommits{l.Len(), commits, "", nil}, oldCommitID, newCommitID); err != nil {
|
||||
if err = CommitRepoAction(userID, user.Id, userName, user.Email,
|
||||
repo.ID, repoUserName, repoName, refName, ListToPushCommits(l), oldCommitID, newCommitID); err != nil {
|
||||
return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -25,11 +25,10 @@ import (
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/nfnt/resize"
|
||||
|
||||
"github.com/gogits/git-shell"
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/modules/avatar"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
oldgit "github.com/gogits/gogs/modules/git"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
@@ -76,6 +75,8 @@ type User struct {
|
||||
|
||||
// Remember visibility choice for convenience, true for private
|
||||
LastRepoVisibility bool
|
||||
// Maximum repository creation limit, -1 means use gloabl default
|
||||
MaxRepoCreation int `xorm:"NOT NULL DEFAULT -1"`
|
||||
|
||||
// Permissions.
|
||||
IsActive bool
|
||||
@@ -102,6 +103,12 @@ type User struct {
|
||||
Members []*User `xorm:"-"`
|
||||
}
|
||||
|
||||
func (u *User) BeforeUpdate() {
|
||||
if u.MaxRepoCreation < -1 {
|
||||
u.MaxRepoCreation = -1
|
||||
}
|
||||
}
|
||||
|
||||
func (u *User) AfterSet(colName string, _ xorm.Cell) {
|
||||
switch colName {
|
||||
case "full_name":
|
||||
@@ -111,12 +118,34 @@ func (u *User) AfterSet(colName string, _ xorm.Cell) {
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if user login type is LOGIN_PLAIN.
|
||||
func (u *User) IsLocal() bool {
|
||||
return u.LoginType <= LOGIN_PLAIN
|
||||
}
|
||||
|
||||
// HasForkedRepo checks if user has already forked a repository with given ID.
|
||||
func (u *User) HasForkedRepo(repoID int64) bool {
|
||||
_, has := HasForkedRepo(u.Id, repoID)
|
||||
return has
|
||||
}
|
||||
|
||||
func (u *User) RepoCreationNum() int {
|
||||
if u.MaxRepoCreation <= -1 {
|
||||
return setting.Repository.MaxCreationLimit
|
||||
}
|
||||
return u.MaxRepoCreation
|
||||
}
|
||||
|
||||
func (u *User) CanCreateRepo() bool {
|
||||
if u.MaxRepoCreation <= -1 {
|
||||
if setting.Repository.MaxCreationLimit <= -1 {
|
||||
return true
|
||||
}
|
||||
return u.NumRepos < setting.Repository.MaxCreationLimit
|
||||
}
|
||||
return u.NumRepos < u.MaxRepoCreation
|
||||
}
|
||||
|
||||
// CanEditGitHook returns true if user can edit Git hooks.
|
||||
func (u *User) CanEditGitHook() bool {
|
||||
return u.IsAdmin || u.AllowGitHook
|
||||
@@ -347,8 +376,8 @@ func (u *User) GetOwnedOrganizations() (err error) {
|
||||
}
|
||||
|
||||
// GetOrganizations returns all organizations that user belongs to.
|
||||
func (u *User) GetOrganizations() error {
|
||||
ous, err := GetOrgUsersByUserId(u.Id)
|
||||
func (u *User) GetOrganizations(all bool) error {
|
||||
ous, err := GetOrgUsersByUserID(u.Id, all)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -446,6 +475,7 @@ func CreateUser(u *User) (err error) {
|
||||
u.Rands = GetUserSalt()
|
||||
u.Salt = GetUserSalt()
|
||||
u.EncodePasswd()
|
||||
u.MaxRepoCreation = -1
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
@@ -858,7 +888,7 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
|
||||
}
|
||||
|
||||
func AddEmailAddress(email *EmailAddress) error {
|
||||
email.Email = strings.ToLower(email.Email)
|
||||
email.Email = strings.ToLower(strings.TrimSpace(email.Email))
|
||||
used, err := IsEmailUsed(email.Email)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -870,6 +900,29 @@ func AddEmailAddress(email *EmailAddress) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func AddEmailAddresses(emails []*EmailAddress) error {
|
||||
if len(emails) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if any of them has been used
|
||||
for i := range emails {
|
||||
emails[i].Email = strings.ToLower(strings.TrimSpace(emails[i].Email))
|
||||
used, err := IsEmailUsed(emails[i].Email)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if used {
|
||||
return ErrEmailAlreadyUsed{emails[i].Email}
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := x.Insert(emails); err != nil {
|
||||
return fmt.Errorf("Insert: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (email *EmailAddress) Activate() error {
|
||||
email.IsActivated = true
|
||||
if _, err := x.Id(email.ID).AllCols().Update(email); err != nil {
|
||||
@@ -884,20 +937,23 @@ func (email *EmailAddress) Activate() error {
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteEmailAddress(email *EmailAddress) error {
|
||||
has, err := x.Get(email)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return ErrEmailNotExist
|
||||
func DeleteEmailAddress(email *EmailAddress) (err error) {
|
||||
if email.ID > 0 {
|
||||
_, err = x.Id(email.ID).Delete(new(EmailAddress))
|
||||
} else {
|
||||
_, err = x.Where("email=?", email.Email).Delete(new(EmailAddress))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = x.Id(email.ID).Delete(email); err != nil {
|
||||
return err
|
||||
func DeleteEmailAddresses(emails []*EmailAddress) (err error) {
|
||||
for i := range emails {
|
||||
if err = DeleteEmailAddress(emails[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func MakeEmailPrimary(email *EmailAddress) error {
|
||||
@@ -940,11 +996,11 @@ func MakeEmailPrimary(email *EmailAddress) error {
|
||||
// UserCommit represents a commit with validation of user.
|
||||
type UserCommit struct {
|
||||
User *User
|
||||
*oldgit.Commit
|
||||
*git.Commit
|
||||
}
|
||||
|
||||
// ValidateCommitWithEmail chceck if author's e-mail of commit is corresponsind to a user.
|
||||
func ValidateCommitWithEmail(c *oldgit.Commit) *User {
|
||||
func ValidateCommitWithEmail(c *git.Commit) *User {
|
||||
u, err := GetUserByEmail(c.Author.Email)
|
||||
if err != nil {
|
||||
return nil
|
||||
@@ -961,7 +1017,7 @@ func ValidateCommitsWithEmails(oldCommits *list.List) *list.List {
|
||||
e = oldCommits.Front()
|
||||
)
|
||||
for e != nil {
|
||||
c := e.Value.(*oldgit.Commit)
|
||||
c := e.Value.(*git.Commit)
|
||||
|
||||
if v, ok := emails[c.Author.Email]; !ok {
|
||||
u, _ = GetUserByEmail(c.Author.Email)
|
||||
|
||||
@@ -10,9 +10,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gogits/git-module"
|
||||
api "github.com/gogits/go-gogs-client"
|
||||
|
||||
"github.com/gogits/gogs/modules/git"
|
||||
)
|
||||
|
||||
type SlackMeta struct {
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
|
||||
"github.com/gogits/git-shell"
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
@@ -31,6 +31,7 @@ type AdminEditUserForm struct {
|
||||
Password string `binding:"MaxSize(255)"`
|
||||
Website string `binding:"MaxSize(50)"`
|
||||
Location string `binding:"MaxSize(50)"`
|
||||
MaxRepoCreation int
|
||||
Active bool
|
||||
Admin bool
|
||||
AllowGitHook bool
|
||||
|
||||
@@ -25,11 +25,12 @@ func (f *CreateOrgForm) Validate(ctx *macaron.Context, errs binding.Errors) bind
|
||||
}
|
||||
|
||||
type UpdateOrgSettingForm struct {
|
||||
Name string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
|
||||
FullName string `binding:"MaxSize(100)"`
|
||||
Description string `binding:"MaxSize(255)"`
|
||||
Website string `binding:"Url;MaxSize(100)"`
|
||||
Location string `binding:"MaxSize(50)"`
|
||||
Name string `binding:"Required;AlphaDashDot;MaxSize(35)" locale:"org.org_name_holder"`
|
||||
FullName string `binding:"MaxSize(100)"`
|
||||
Description string `binding:"MaxSize(255)"`
|
||||
Website string `binding:"Url;MaxSize(100)"`
|
||||
Location string `binding:"MaxSize(50)"`
|
||||
MaxRepoCreation int
|
||||
}
|
||||
|
||||
func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
|
||||
@@ -81,15 +81,18 @@ func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) {
|
||||
}
|
||||
|
||||
type RepoSettingForm struct {
|
||||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||
Description string `binding:"MaxSize(255)"`
|
||||
Website string `binding:"Url;MaxSize(100)"`
|
||||
Branch string
|
||||
Interval int
|
||||
Private bool
|
||||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||
Description string `binding:"MaxSize(255)"`
|
||||
Website string `binding:"Url;MaxSize(100)"`
|
||||
Branch string
|
||||
Interval int
|
||||
MirrorAddress string
|
||||
Private bool
|
||||
|
||||
// Advanced settings
|
||||
EnableWiki bool
|
||||
EnableExternalWiki bool
|
||||
ExternalWikiURL string
|
||||
EnableIssues bool
|
||||
EnableExternalTracker bool
|
||||
TrackerURLFormat string
|
||||
|
||||
@@ -87,12 +87,12 @@ func (f *SignInForm) Validate(ctx *macaron.Context, errs binding.Errors) binding
|
||||
// \/ \/ \/ \/ \/
|
||||
|
||||
type UpdateProfileForm struct {
|
||||
Name string `binding:"Required;MaxSize(35)"`
|
||||
Name string `binding:"OmitEmpty;MaxSize(35)"`
|
||||
FullName string `binding:"MaxSize(100)"`
|
||||
Email string `binding:"Required;Email;MaxSize(254)"`
|
||||
Website string `binding:"Url;MaxSize(100)"`
|
||||
Location string `binding:"MaxSize(50)"`
|
||||
Gravatar string `binding:"Required;Email;MaxSize(254)"`
|
||||
Gravatar string `binding:"OmitEmpty;Email;MaxSize(254)"`
|
||||
}
|
||||
|
||||
func (f *UpdateProfileForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
|
||||
@@ -133,7 +133,7 @@ var (
|
||||
MentionPattern = regexp.MustCompile(`(\s|^)@[0-9a-zA-Z_\.]+`)
|
||||
commitPattern = regexp.MustCompile(`(\s|^)https?.*commit/[0-9a-zA-Z]+(#+[0-9a-zA-Z-]*)?`)
|
||||
issueFullPattern = regexp.MustCompile(`(\s|^)https?.*issues/[0-9]+(#+[0-9a-zA-Z-]*)?`)
|
||||
issueIndexPattern = regexp.MustCompile(`( |^)#[0-9]+\b`)
|
||||
issueIndexPattern = regexp.MustCompile(`( |^|\()#[0-9]+\b`)
|
||||
sha1CurrentPattern = regexp.MustCompile(`\b[0-9a-f]{40}\b`)
|
||||
)
|
||||
|
||||
@@ -156,8 +156,8 @@ func RenderIssueIndexPattern(rawBytes []byte, urlPrefix string, metas map[string
|
||||
for _, m := range ms {
|
||||
var space string
|
||||
m2 := m
|
||||
if m2[0] == ' ' {
|
||||
space = " "
|
||||
if m2[0] != '#' {
|
||||
space = string(m2[0])
|
||||
m2 = m2[1:]
|
||||
}
|
||||
if metas == nil {
|
||||
|
||||
@@ -22,8 +22,7 @@ import (
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/Unknwon/i18n"
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
|
||||
"github.com/gogits/chardet"
|
||||
"golang.org/x/net/html/charset"
|
||||
|
||||
"github.com/gogits/gogs/modules/avatar"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
@@ -52,13 +51,9 @@ func ShortSha(sha1 string) string {
|
||||
return sha1
|
||||
}
|
||||
|
||||
func DetectEncoding(content []byte) (string, error) {
|
||||
detector := chardet.NewTextDetector()
|
||||
result, err := detector.DetectBest(content)
|
||||
if result.Charset != "UTF-8" && len(setting.Repository.AnsiCharset) > 0 {
|
||||
return setting.Repository.AnsiCharset, err
|
||||
}
|
||||
return result.Charset, err
|
||||
func DetectEncoding(content []byte) string {
|
||||
_, name, _ := charset.DetermineEncoding(content, setting.Repository.AnsiCharset)
|
||||
return name
|
||||
}
|
||||
|
||||
func BasicAuthDecode(encoded string) (string, string, error) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,26 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
type Blob struct {
|
||||
repo *Repository
|
||||
*TreeEntry
|
||||
}
|
||||
|
||||
func (b *Blob) Data() (io.Reader, error) {
|
||||
stdout, stderr, err := com.ExecCmdDirBytes(b.repo.Path, "git", "show", b.ID.String())
|
||||
if err != nil {
|
||||
return nil, errors.New(string(stderr))
|
||||
}
|
||||
return bytes.NewBuffer(stdout), nil
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"container/list"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Commit represents a git commit.
|
||||
type Commit struct {
|
||||
Tree
|
||||
ID sha1 // The id of this commit object
|
||||
Author *Signature
|
||||
Committer *Signature
|
||||
CommitMessage string
|
||||
|
||||
parents []sha1 // sha1 strings
|
||||
submodules map[string]*SubModule
|
||||
}
|
||||
|
||||
// Return the commit message. Same as retrieving CommitMessage directly.
|
||||
func (c *Commit) Message() string {
|
||||
return c.CommitMessage
|
||||
}
|
||||
|
||||
func (c *Commit) Summary() string {
|
||||
return strings.Split(c.CommitMessage, "\n")[0]
|
||||
}
|
||||
|
||||
// Return oid of the parent number n (0-based index). Return nil if no such parent exists.
|
||||
func (c *Commit) ParentId(n int) (id sha1, err error) {
|
||||
if n >= len(c.parents) {
|
||||
err = IDNotExist
|
||||
return
|
||||
}
|
||||
return c.parents[n], nil
|
||||
}
|
||||
|
||||
// Return parent number n (0-based index)
|
||||
func (c *Commit) Parent(n int) (*Commit, error) {
|
||||
id, err := c.ParentId(n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parent, err := c.repo.getCommit(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parent, nil
|
||||
}
|
||||
|
||||
// Return the number of parents of the commit. 0 if this is the
|
||||
// root commit, otherwise 1,2,...
|
||||
func (c *Commit) ParentCount() int {
|
||||
return len(c.parents)
|
||||
}
|
||||
|
||||
func (c *Commit) CommitsBefore() (*list.List, error) {
|
||||
return c.repo.getCommitsBefore(c.ID)
|
||||
}
|
||||
|
||||
func (c *Commit) CommitsBeforeUntil(commitId string) (*list.List, error) {
|
||||
ec, err := c.repo.GetCommit(commitId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.repo.CommitsBetween(c, ec)
|
||||
}
|
||||
|
||||
func (c *Commit) CommitsCount() (int, error) {
|
||||
return c.repo.commitsCount(c.ID)
|
||||
}
|
||||
|
||||
func (c *Commit) SearchCommits(keyword string) (*list.List, error) {
|
||||
return c.repo.searchCommits(c.ID, keyword)
|
||||
}
|
||||
|
||||
func (c *Commit) CommitsByRange(page int) (*list.List, error) {
|
||||
return c.repo.commitsByRange(c.ID, page)
|
||||
}
|
||||
|
||||
func (c *Commit) GetCommitOfRelPath(relPath string) (*Commit, error) {
|
||||
return c.repo.getCommitOfRelPath(c.ID, relPath)
|
||||
}
|
||||
|
||||
func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
|
||||
modules, err := c.GetSubModules()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return modules[entryname], nil
|
||||
}
|
||||
|
||||
func (c *Commit) GetSubModules() (map[string]*SubModule, error) {
|
||||
if c.submodules != nil {
|
||||
return c.submodules, nil
|
||||
}
|
||||
|
||||
entry, err := c.GetTreeEntryByPath(".gitmodules")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rd, err := entry.Blob().Data()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(rd)
|
||||
c.submodules = make(map[string]*SubModule)
|
||||
var ismodule bool
|
||||
var path string
|
||||
for scanner.Scan() {
|
||||
if strings.HasPrefix(scanner.Text(), "[submodule") {
|
||||
ismodule = true
|
||||
continue
|
||||
}
|
||||
if ismodule {
|
||||
fields := strings.Split(scanner.Text(), "=")
|
||||
k := strings.TrimSpace(fields[0])
|
||||
if k == "path" {
|
||||
path = strings.TrimSpace(fields[1])
|
||||
} else if k == "url" {
|
||||
c.submodules[path] = &SubModule{path, strings.TrimSpace(fields[1])}
|
||||
ismodule = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c.submodules, nil
|
||||
}
|
||||
|
||||
func isImageFile(data []byte) (string, bool) {
|
||||
contentType := http.DetectContentType(data)
|
||||
if strings.Index(contentType, "image/") != -1 {
|
||||
return contentType, true
|
||||
}
|
||||
return contentType, false
|
||||
}
|
||||
|
||||
func (c *Commit) IsImageFile(name string) bool {
|
||||
blob, err := c.GetBlobByPath(name)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
dataRc, err := blob.Data()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
buf := make([]byte, 1024)
|
||||
n, _ := dataRc.Read(buf)
|
||||
if n > 0 {
|
||||
buf = buf[:n]
|
||||
}
|
||||
_, isImage := isImageFile(buf)
|
||||
return isImage
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
type ArchiveType int
|
||||
|
||||
const (
|
||||
ZIP ArchiveType = iota + 1
|
||||
TARGZ
|
||||
)
|
||||
|
||||
func (c *Commit) CreateArchive(path string, archiveType ArchiveType) error {
|
||||
var format string
|
||||
switch archiveType {
|
||||
case ZIP:
|
||||
format = "zip"
|
||||
case TARGZ:
|
||||
format = "tar.gz"
|
||||
default:
|
||||
return fmt.Errorf("unknown format: %v", archiveType)
|
||||
}
|
||||
|
||||
_, stderr, err := com.ExecCmdDir(c.repo.Path, "git", "archive", "--format="+format, "-o", path, c.ID.String())
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s", stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ErrUnsupportedVersion struct {
|
||||
Required string
|
||||
}
|
||||
|
||||
func IsErrUnsupportedVersion(err error) bool {
|
||||
_, ok := err.(ErrUnsupportedVersion)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUnsupportedVersion) Error() string {
|
||||
return fmt.Sprintf("Operation requires higher version [required: %s]", err.Required)
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
// hookNames is a list of Git hooks' name that are supported.
|
||||
var hookNames = []string{
|
||||
"applypatch-msg",
|
||||
"pre-applypatch",
|
||||
"post-applypatch",
|
||||
"pre-commit",
|
||||
"prepare-commit-msg",
|
||||
"commit-msg",
|
||||
"post-commit",
|
||||
"pre-rebase",
|
||||
"post-checkout",
|
||||
"post-merge",
|
||||
"pre-push",
|
||||
// "update",
|
||||
"post-receive",
|
||||
"post-update",
|
||||
"push-to-checkout",
|
||||
"pre-auto-gc",
|
||||
"post-rewrite",
|
||||
}
|
||||
|
||||
var (
|
||||
ErrNotValidHook = errors.New("not a valid Git hook")
|
||||
)
|
||||
|
||||
// IsValidHookName returns true if given name is a valid Git hook.
|
||||
func IsValidHookName(name string) bool {
|
||||
for _, hn := range hookNames {
|
||||
if hn == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Hook represents a Git hook.
|
||||
type Hook struct {
|
||||
name string
|
||||
IsActive bool // Indicates whether repository has this hook.
|
||||
Content string // Content of hook if it's active.
|
||||
Sample string // Sample content from Git.
|
||||
path string // Hook file path.
|
||||
}
|
||||
|
||||
// GetHook returns a Git hook by given name and repository.
|
||||
func GetHook(repoPath, name string) (*Hook, error) {
|
||||
if !IsValidHookName(name) {
|
||||
return nil, ErrNotValidHook
|
||||
}
|
||||
h := &Hook{
|
||||
name: name,
|
||||
path: path.Join(repoPath, "hooks", name),
|
||||
}
|
||||
if isFile(h.path) {
|
||||
data, err := ioutil.ReadFile(h.path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.IsActive = true
|
||||
h.Content = string(data)
|
||||
} else if isFile(h.path + ".sample") {
|
||||
data, err := ioutil.ReadFile(h.path + ".sample")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.Sample = string(data)
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
func (h *Hook) Name() string {
|
||||
return h.name
|
||||
}
|
||||
|
||||
// Update updates hook settings.
|
||||
func (h *Hook) Update() error {
|
||||
if len(strings.TrimSpace(h.Content)) == 0 {
|
||||
if com.IsExist(h.path) {
|
||||
return os.Remove(h.path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return ioutil.WriteFile(h.path, []byte(strings.Replace(h.Content, "\r", "", -1)), os.ModePerm)
|
||||
}
|
||||
|
||||
// ListHooks returns a list of Git hooks of given repository.
|
||||
func ListHooks(repoPath string) (_ []*Hook, err error) {
|
||||
if !isDir(path.Join(repoPath, "hooks")) {
|
||||
return nil, errors.New("hooks path does not exist")
|
||||
}
|
||||
|
||||
hooks := make([]*Hook, len(hookNames))
|
||||
for i, name := range hookNames {
|
||||
hooks[i], err = GetHook(repoPath, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return hooks, nil
|
||||
}
|
||||
|
||||
func (repo *Repository) GetHook(name string) (*Hook, error) {
|
||||
return GetHook(repo.Path, name)
|
||||
}
|
||||
|
||||
func (repo *Repository) Hooks() ([]*Hook, error) {
|
||||
return ListHooks(repo.Path)
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Repository represents a Git repository.
|
||||
type Repository struct {
|
||||
Path string
|
||||
|
||||
commitCache map[sha1]*Commit
|
||||
tagCache map[sha1]*Tag
|
||||
}
|
||||
|
||||
// OpenRepository opens the repository at the given path.
|
||||
func OpenRepository(repoPath string) (*Repository, error) {
|
||||
repoPath, err := filepath.Abs(repoPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !isDir(repoPath) {
|
||||
return nil, errors.New("no such file or directory")
|
||||
}
|
||||
|
||||
return &Repository{Path: repoPath}, nil
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
func IsBranchExist(repoPath, branchName string) bool {
|
||||
_, _, err := com.ExecCmdDir(repoPath, "git", "show-ref", "--verify", "refs/heads/"+branchName)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (repo *Repository) IsBranchExist(branchName string) bool {
|
||||
return IsBranchExist(repo.Path, branchName)
|
||||
}
|
||||
|
||||
func (repo *Repository) GetBranches() ([]string, error) {
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--heads")
|
||||
if err != nil {
|
||||
return nil, concatenateError(err, stderr)
|
||||
}
|
||||
infos := strings.Split(stdout, "\n")
|
||||
branches := make([]string, len(infos)-1)
|
||||
for i, info := range infos[:len(infos)-1] {
|
||||
parts := strings.Split(info, " ")
|
||||
if len(parts) != 2 {
|
||||
continue // NOTE: I should believe git will not give me wrong string.
|
||||
}
|
||||
branches[i] = strings.TrimPrefix(parts[1], "refs/heads/")
|
||||
}
|
||||
return branches, nil
|
||||
}
|
||||
|
||||
// SetDefaultBranch sets default branch of repository.
|
||||
func (repo *Repository) SetDefaultBranch(branchName string) error {
|
||||
if gitVer.LessThan(MustParseVersion("1.7.10")) {
|
||||
return ErrUnsupportedVersion{"1.7.10"}
|
||||
}
|
||||
|
||||
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "symbolic-ref", "HEAD", "refs/heads/"+branchName)
|
||||
if err != nil {
|
||||
return concatenateError(err, stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,341 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
func (repo *Repository) getCommitIdOfRef(refpath string) (string, error) {
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--verify", refpath)
|
||||
if err != nil {
|
||||
return "", errors.New(stderr)
|
||||
}
|
||||
return strings.Split(stdout, " ")[0], nil
|
||||
}
|
||||
|
||||
func (repo *Repository) GetCommitIdOfBranch(branchName string) (string, error) {
|
||||
return repo.getCommitIdOfRef("refs/heads/" + branchName)
|
||||
}
|
||||
|
||||
// get branch's last commit or a special commit by id string
|
||||
func (repo *Repository) GetCommitOfBranch(branchName string) (*Commit, error) {
|
||||
commitId, err := repo.GetCommitIdOfBranch(branchName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repo.GetCommit(commitId)
|
||||
}
|
||||
|
||||
func (repo *Repository) GetCommitIdOfTag(tagName string) (string, error) {
|
||||
return repo.getCommitIdOfRef("refs/tags/" + tagName)
|
||||
}
|
||||
|
||||
func (repo *Repository) GetCommitOfTag(tagName string) (*Commit, error) {
|
||||
tag, err := repo.GetTag(tagName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tag.Commit()
|
||||
}
|
||||
|
||||
// Parse commit information from the (uncompressed) raw
|
||||
// data from the commit object.
|
||||
// \n\n separate headers from message
|
||||
func parseCommitData(data []byte) (*Commit, error) {
|
||||
commit := new(Commit)
|
||||
commit.parents = make([]sha1, 0, 1)
|
||||
// we now have the contents of the commit object. Let's investigate...
|
||||
nextline := 0
|
||||
l:
|
||||
for {
|
||||
eol := bytes.IndexByte(data[nextline:], '\n')
|
||||
switch {
|
||||
case eol > 0:
|
||||
line := data[nextline : nextline+eol]
|
||||
spacepos := bytes.IndexByte(line, ' ')
|
||||
reftype := line[:spacepos]
|
||||
switch string(reftype) {
|
||||
case "tree":
|
||||
id, err := NewIdFromString(string(line[spacepos+1:]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
commit.Tree.ID = id
|
||||
case "parent":
|
||||
// A commit can have one or more parents
|
||||
oid, err := NewIdFromString(string(line[spacepos+1:]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
commit.parents = append(commit.parents, oid)
|
||||
case "author":
|
||||
sig, err := newSignatureFromCommitline(line[spacepos+1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
commit.Author = sig
|
||||
case "committer":
|
||||
sig, err := newSignatureFromCommitline(line[spacepos+1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
commit.Committer = sig
|
||||
}
|
||||
nextline += eol + 1
|
||||
case eol == 0:
|
||||
commit.CommitMessage = string(data[nextline+1:])
|
||||
break l
|
||||
default:
|
||||
break l
|
||||
}
|
||||
}
|
||||
return commit, nil
|
||||
}
|
||||
|
||||
func (repo *Repository) getCommit(id sha1) (*Commit, error) {
|
||||
if repo.commitCache != nil {
|
||||
if c, ok := repo.commitCache[id]; ok {
|
||||
return c, nil
|
||||
}
|
||||
} else {
|
||||
repo.commitCache = make(map[sha1]*Commit, 10)
|
||||
}
|
||||
|
||||
data, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "cat-file", "-p", id.String())
|
||||
if err != nil {
|
||||
return nil, concatenateError(err, string(stderr))
|
||||
}
|
||||
|
||||
commit, err := parseCommitData(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
commit.repo = repo
|
||||
commit.ID = id
|
||||
|
||||
repo.commitCache[id] = commit
|
||||
return commit, nil
|
||||
}
|
||||
|
||||
// Find the commit object in the repository.
|
||||
func (repo *Repository) GetCommit(commitId string) (*Commit, error) {
|
||||
id, err := NewIdFromString(commitId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return repo.getCommit(id)
|
||||
}
|
||||
|
||||
func (repo *Repository) commitsCount(id sha1) (int, error) {
|
||||
if gitVer.LessThan(MustParseVersion("1.8.0")) {
|
||||
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log",
|
||||
"--pretty=format:''", id.String())
|
||||
if err != nil {
|
||||
return 0, errors.New(string(stderr))
|
||||
}
|
||||
return len(bytes.Split(stdout, []byte("\n"))), nil
|
||||
}
|
||||
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count", id.String())
|
||||
if err != nil {
|
||||
return 0, errors.New(stderr)
|
||||
}
|
||||
return com.StrTo(strings.TrimSpace(stdout)).Int()
|
||||
}
|
||||
|
||||
func (repo *Repository) CommitsCount(commitId string) (int, error) {
|
||||
id, err := NewIdFromString(commitId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return repo.commitsCount(id)
|
||||
}
|
||||
|
||||
func (repo *Repository) commitsCountBetween(start, end sha1) (int, error) {
|
||||
if gitVer.LessThan(MustParseVersion("1.8.0")) {
|
||||
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log",
|
||||
"--pretty=format:''", start.String()+"..."+end.String())
|
||||
if err != nil {
|
||||
return 0, errors.New(string(stderr))
|
||||
}
|
||||
return len(bytes.Split(stdout, []byte("\n"))), nil
|
||||
}
|
||||
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count",
|
||||
start.String()+"..."+end.String())
|
||||
if err != nil {
|
||||
return 0, errors.New(stderr)
|
||||
}
|
||||
return com.StrTo(strings.TrimSpace(stdout)).Int()
|
||||
}
|
||||
|
||||
func (repo *Repository) CommitsCountBetween(startCommitID, endCommitID string) (int, error) {
|
||||
start, err := NewIdFromString(startCommitID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
end, err := NewIdFromString(endCommitID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return repo.commitsCountBetween(start, end)
|
||||
}
|
||||
|
||||
func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (int, error) {
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "diff", "--name-only",
|
||||
startCommitID+"..."+endCommitID)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("list changed files: %v", concatenateError(err, stderr))
|
||||
}
|
||||
return len(strings.Split(stdout, "\n")) - 1, nil
|
||||
}
|
||||
|
||||
// used only for single tree, (]
|
||||
func (repo *Repository) CommitsBetween(last *Commit, before *Commit) (*list.List, error) {
|
||||
l := list.New()
|
||||
if last == nil || last.ParentCount() == 0 {
|
||||
return l, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
cur := last
|
||||
for {
|
||||
if cur.ID.Equal(before.ID) {
|
||||
break
|
||||
}
|
||||
l.PushBack(cur)
|
||||
if cur.ParentCount() == 0 {
|
||||
break
|
||||
}
|
||||
cur, err = cur.Parent(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (repo *Repository) commitsBefore(lock *sync.Mutex, l *list.List, parent *list.Element, id sha1, limit int) error {
|
||||
commit, err := repo.getCommit(id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getCommit: %v", err)
|
||||
}
|
||||
|
||||
var e *list.Element
|
||||
if parent == nil {
|
||||
e = l.PushBack(commit)
|
||||
} else {
|
||||
var in = parent
|
||||
for {
|
||||
if in == nil {
|
||||
break
|
||||
} else if in.Value.(*Commit).ID.Equal(commit.ID) {
|
||||
return nil
|
||||
} else {
|
||||
if in.Next() == nil {
|
||||
break
|
||||
}
|
||||
if in.Value.(*Commit).Committer.When.Equal(commit.Committer.When) {
|
||||
break
|
||||
}
|
||||
|
||||
if in.Value.(*Commit).Committer.When.After(commit.Committer.When) &&
|
||||
in.Next().Value.(*Commit).Committer.When.Before(commit.Committer.When) {
|
||||
break
|
||||
}
|
||||
}
|
||||
in = in.Next()
|
||||
}
|
||||
|
||||
e = l.InsertAfter(commit, in)
|
||||
}
|
||||
|
||||
var pr = parent
|
||||
if commit.ParentCount() > 1 {
|
||||
pr = e
|
||||
}
|
||||
|
||||
for i := 0; i < commit.ParentCount(); i++ {
|
||||
id, err := commit.ParentId(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = repo.commitsBefore(lock, l, pr, id, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (repo *Repository) FileCommitsCount(branch, file string) (int, error) {
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count",
|
||||
branch, "--", file)
|
||||
if err != nil {
|
||||
return 0, errors.New(stderr)
|
||||
}
|
||||
return com.StrTo(strings.TrimSpace(stdout)).Int()
|
||||
}
|
||||
|
||||
func (repo *Repository) CommitsByFileAndRange(branch, file string, page int) (*list.List, error) {
|
||||
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", branch,
|
||||
"--skip="+com.ToStr((page-1)*50), "--max-count=50", prettyLogFormat, "--", file)
|
||||
if err != nil {
|
||||
return nil, errors.New(string(stderr))
|
||||
}
|
||||
return parsePrettyFormatLog(repo, stdout)
|
||||
}
|
||||
|
||||
func (repo *Repository) getCommitsBefore(id sha1) (*list.List, error) {
|
||||
l := list.New()
|
||||
lock := new(sync.Mutex)
|
||||
return l, repo.commitsBefore(lock, l, nil, id, 0)
|
||||
}
|
||||
|
||||
func (repo *Repository) searchCommits(id sha1, keyword string) (*list.List, error) {
|
||||
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(), "-100",
|
||||
"-i", "--grep="+keyword, prettyLogFormat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(stderr) > 0 {
|
||||
return nil, errors.New(string(stderr))
|
||||
}
|
||||
return parsePrettyFormatLog(repo, stdout)
|
||||
}
|
||||
|
||||
var CommitsRangeSize = 50
|
||||
|
||||
func (repo *Repository) commitsByRange(id sha1, page int) (*list.List, error) {
|
||||
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", id.String(),
|
||||
"--skip="+com.ToStr((page-1)*CommitsRangeSize), "--max-count="+com.ToStr(CommitsRangeSize), prettyLogFormat)
|
||||
if err != nil {
|
||||
return nil, errors.New(string(stderr))
|
||||
}
|
||||
return parsePrettyFormatLog(repo, stdout)
|
||||
}
|
||||
|
||||
func (repo *Repository) getCommitOfRelPath(id sha1, relPath string) (*Commit, error) {
|
||||
stdout, _, err := com.ExecCmdDir(repo.Path, "git", "log", "-1", prettyLogFormat, id.String(), "--", relPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, err = NewIdFromString(string(stdout))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return repo.getCommit(id)
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
type ObjectType string
|
||||
|
||||
const (
|
||||
COMMIT ObjectType = "commit"
|
||||
TREE ObjectType = "tree"
|
||||
BLOB ObjectType = "blob"
|
||||
TAG ObjectType = "tag"
|
||||
)
|
||||
@@ -1,104 +0,0 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
type PullRequestInfo struct {
|
||||
MergeBase string
|
||||
Commits *list.List
|
||||
// Diff *Diff
|
||||
NumFiles int
|
||||
}
|
||||
|
||||
// GetMergeBase checks and returns merge base of two branches.
|
||||
func (repo *Repository) GetMergeBase(remoteBranch, headBranch string) (string, error) {
|
||||
// Get merge base commit.
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "merge-base", remoteBranch, headBranch)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("get merge base: %v", concatenateError(err, stderr))
|
||||
}
|
||||
return strings.TrimSpace(stdout), nil
|
||||
}
|
||||
|
||||
// AddRemote adds a remote to repository.
|
||||
func (repo *Repository) AddRemote(name, path string) error {
|
||||
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "add", "-f", name, path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("add remote(%s - %s): %v", name, path, concatenateError(err, stderr))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveRemote removes a remote from repository.
|
||||
func (repo *Repository) RemoveRemote(name string) error {
|
||||
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "remove", name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("remove remote(%s): %v", name, concatenateError(err, stderr))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPullRequestInfo generates and returns pull request information
|
||||
// between base and head branches of repositories.
|
||||
func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch string) (_ *PullRequestInfo, err error) {
|
||||
// Add a temporary remote.
|
||||
tmpRemote := com.ToStr(time.Now().UnixNano())
|
||||
if err = repo.AddRemote(tmpRemote, basePath); err != nil {
|
||||
return nil, fmt.Errorf("AddRemote: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
repo.RemoveRemote(tmpRemote)
|
||||
}()
|
||||
|
||||
remoteBranch := "remotes/" + tmpRemote + "/" + baseBranch
|
||||
|
||||
prInfo := new(PullRequestInfo)
|
||||
prInfo.MergeBase, err = repo.GetMergeBase(remoteBranch, headBranch)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetMergeBase: %v", err)
|
||||
}
|
||||
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "log", prInfo.MergeBase+"..."+headBranch, prettyLogFormat)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list diff logs: %v", concatenateError(err, stderr))
|
||||
}
|
||||
prInfo.Commits, err = parsePrettyFormatLog(repo, []byte(stdout))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsePrettyFormatLog: %v", err)
|
||||
}
|
||||
|
||||
// Count number of changed files.
|
||||
stdout, stderr, err = com.ExecCmdDir(repo.Path, "git", "diff", "--name-only", remoteBranch+"..."+headBranch)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list changed files: %v", concatenateError(err, stderr))
|
||||
}
|
||||
prInfo.NumFiles = len(strings.Split(stdout, "\n")) - 1
|
||||
|
||||
return prInfo, nil
|
||||
}
|
||||
|
||||
// GetPatch generates and returns patch data between given branches.
|
||||
func (repo *Repository) GetPatch(mergeBase, headBranch string) ([]byte, error) {
|
||||
stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "diff", "-p", "--binary", mergeBase, headBranch)
|
||||
if err != nil {
|
||||
return nil, concatenateError(err, string(stderr))
|
||||
}
|
||||
|
||||
return stdout, nil
|
||||
}
|
||||
|
||||
// Merge merges pull request from head repository and branch.
|
||||
func (repo *Repository) Merge(headRepoPath string, baseBranch, headBranch string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
func IsTagExist(repoPath, tagName string) bool {
|
||||
_, _, err := com.ExecCmdDir(repoPath, "git", "show-ref", "--verify", "refs/tags/"+tagName)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (repo *Repository) IsTagExist(tagName string) bool {
|
||||
return IsTagExist(repo.Path, tagName)
|
||||
}
|
||||
|
||||
func (repo *Repository) getTagsReversed() ([]string, error) {
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l", "--sort=-v:refname")
|
||||
if err != nil {
|
||||
return nil, concatenateError(err, stderr)
|
||||
}
|
||||
tags := strings.Split(stdout, "\n")
|
||||
return tags[:len(tags)-1], nil
|
||||
}
|
||||
|
||||
// GetTags returns all tags of given repository.
|
||||
func (repo *Repository) GetTags() ([]string, error) {
|
||||
if gitVer.AtLeast(MustParseVersion("2.0.0")) {
|
||||
return repo.getTagsReversed()
|
||||
}
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l")
|
||||
if err != nil {
|
||||
return nil, concatenateError(err, stderr)
|
||||
}
|
||||
tags := strings.Split(stdout, "\n")
|
||||
return tags[:len(tags)-1], nil
|
||||
}
|
||||
|
||||
func (repo *Repository) CreateTag(tagName, idStr string) error {
|
||||
_, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", tagName, idStr)
|
||||
if err != nil {
|
||||
return errors.New(stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (repo *Repository) getTag(id sha1) (*Tag, error) {
|
||||
if repo.tagCache != nil {
|
||||
if t, ok := repo.tagCache[id]; ok {
|
||||
return t, nil
|
||||
}
|
||||
} else {
|
||||
repo.tagCache = make(map[sha1]*Tag, 10)
|
||||
}
|
||||
|
||||
// Get tag type.
|
||||
tp, stderr, err := com.ExecCmdDir(repo.Path, "git", "cat-file", "-t", id.String())
|
||||
if err != nil {
|
||||
return nil, errors.New(stderr)
|
||||
}
|
||||
tp = strings.TrimSpace(tp)
|
||||
|
||||
// Tag is a commit.
|
||||
if ObjectType(tp) == COMMIT {
|
||||
tag := &Tag{
|
||||
ID: id,
|
||||
Object: id,
|
||||
Type: string(COMMIT),
|
||||
repo: repo,
|
||||
}
|
||||
repo.tagCache[id] = tag
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
// Tag with message.
|
||||
data, bytErr, err := com.ExecCmdDirBytes(repo.Path, "git", "cat-file", "-p", id.String())
|
||||
if err != nil {
|
||||
return nil, errors.New(string(bytErr))
|
||||
}
|
||||
|
||||
tag, err := parseTagData(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tag.ID = id
|
||||
tag.repo = repo
|
||||
|
||||
repo.tagCache[id] = tag
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
// GetTag returns a Git tag by given name.
|
||||
func (repo *Repository) GetTag(tagName string) (*Tag, error) {
|
||||
stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--tags", tagName)
|
||||
if err != nil {
|
||||
return nil, errors.New(stderr)
|
||||
}
|
||||
|
||||
id, err := NewIdFromString(strings.Split(stdout, " ")[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tag, err := repo.getTag(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tag.Name = tagName
|
||||
return tag, nil
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
// Find the tree object in the repository.
|
||||
func (repo *Repository) GetTree(idStr string) (*Tree, error) {
|
||||
id, err := NewIdFromString(idStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repo.getTree(id)
|
||||
}
|
||||
|
||||
func (repo *Repository) getTree(id sha1) (*Tree, error) {
|
||||
treePath := filepathFromSHA1(repo.Path, id.String())
|
||||
if !com.IsFile(treePath) {
|
||||
_, _, err := com.ExecCmdDir(repo.Path, "git", "ls-tree", id.String())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("repo.getTree: %v", ErrNotExist)
|
||||
}
|
||||
}
|
||||
|
||||
return NewTree(repo, id), nil
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
IDNotExist = errors.New("sha1 ID does not exist")
|
||||
)
|
||||
|
||||
type sha1 [20]byte
|
||||
|
||||
// Return true if s has the same sha1 as caller.
|
||||
// Support 40-length-string, []byte, sha1
|
||||
func (id sha1) Equal(s2 interface{}) bool {
|
||||
switch v := s2.(type) {
|
||||
case string:
|
||||
if len(v) != 40 {
|
||||
return false
|
||||
}
|
||||
return v == id.String()
|
||||
case []byte:
|
||||
if len(v) != 20 {
|
||||
return false
|
||||
}
|
||||
for i, v := range v {
|
||||
if id[i] != v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
case sha1:
|
||||
for i, v := range v {
|
||||
if id[i] != v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Return string (hex) representation of the Oid
|
||||
func (s sha1) String() string {
|
||||
result := make([]byte, 0, 40)
|
||||
hexvalues := []byte("0123456789abcdef")
|
||||
for i := 0; i < 20; i++ {
|
||||
result = append(result, hexvalues[s[i]>>4])
|
||||
result = append(result, hexvalues[s[i]&0xf])
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
|
||||
// Create a new sha1 from a 20 byte slice.
|
||||
func NewId(b []byte) (sha1, error) {
|
||||
var id sha1
|
||||
if len(b) != 20 {
|
||||
return id, errors.New("Length must be 20")
|
||||
}
|
||||
|
||||
for i := 0; i < 20; i++ {
|
||||
id[i] = b[i]
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// Create a new sha1 from a Sha1 string of length 40.
|
||||
func NewIdFromString(s string) (sha1, error) {
|
||||
s = strings.TrimSpace(s)
|
||||
var id sha1
|
||||
if len(s) != 40 {
|
||||
return id, fmt.Errorf("Length must be 40")
|
||||
}
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
return NewId(b)
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Author and Committer information
|
||||
type Signature struct {
|
||||
Email string
|
||||
Name string
|
||||
When time.Time
|
||||
}
|
||||
|
||||
// Helper to get a signature from the commit line, which looks like these:
|
||||
// author Patrick Gundlach <gundlach@speedata.de> 1378823654 +0200
|
||||
// author Patrick Gundlach <gundlach@speedata.de> Thu, 07 Apr 2005 22:13:13 +0200
|
||||
// but without the "author " at the beginning (this method should)
|
||||
// be used for author and committer.
|
||||
//
|
||||
// FIXME: include timezone for timestamp!
|
||||
func newSignatureFromCommitline(line []byte) (_ *Signature, err error) {
|
||||
sig := new(Signature)
|
||||
emailStart := bytes.IndexByte(line, '<')
|
||||
sig.Name = string(line[:emailStart-1])
|
||||
emailEnd := bytes.IndexByte(line, '>')
|
||||
sig.Email = string(line[emailStart+1 : emailEnd])
|
||||
|
||||
// Check date format.
|
||||
firstChar := line[emailEnd+2]
|
||||
if firstChar >= 48 && firstChar <= 57 {
|
||||
timestop := bytes.IndexByte(line[emailEnd+2:], ' ')
|
||||
timestring := string(line[emailEnd+2 : emailEnd+2+timestop])
|
||||
seconds, err := strconv.ParseInt(timestring, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sig.When = time.Unix(seconds, 0)
|
||||
} else {
|
||||
sig.When, err = time.Parse("Mon Jan _2 15:04:05 2006 -0700", string(line[emailEnd+2:]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return sig, nil
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright 2015 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func Test_newSignatureFromCommitline(t *testing.T) {
|
||||
Convey("Parse signature from commit line", t, func() {
|
||||
line := "Intern <intern@macbook-intern.(none)> 1445412825 +0200"
|
||||
sig, err := newSignatureFromCommitline([]byte(line))
|
||||
So(err, ShouldBeNil)
|
||||
So(sig, ShouldNotBeNil)
|
||||
})
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
type SubModule struct {
|
||||
Name string
|
||||
Url string
|
||||
}
|
||||
|
||||
// SubModuleFile represents a file with submodule type.
|
||||
type SubModuleFile struct {
|
||||
*Commit
|
||||
|
||||
refUrl string
|
||||
refId string
|
||||
}
|
||||
|
||||
func NewSubModuleFile(c *Commit, refUrl, refId string) *SubModuleFile {
|
||||
return &SubModuleFile{
|
||||
Commit: c,
|
||||
refUrl: refUrl,
|
||||
refId: refId,
|
||||
}
|
||||
}
|
||||
|
||||
// RefUrl guesses and returns reference URL.
|
||||
func (sf *SubModuleFile) RefUrl() string {
|
||||
if sf.refUrl == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
url := strings.TrimSuffix(sf.refUrl, ".git")
|
||||
|
||||
// git://xxx/user/repo
|
||||
if strings.HasPrefix(url, "git://") {
|
||||
return "http://" + strings.TrimPrefix(url, "git://")
|
||||
}
|
||||
|
||||
// http[s]://xxx/user/repo
|
||||
if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
|
||||
return url
|
||||
}
|
||||
|
||||
// sysuser@xxx:user/repo
|
||||
i := strings.Index(url, "@")
|
||||
j := strings.LastIndex(url, ":")
|
||||
if i > -1 && j > -1 {
|
||||
// fix problem with reverse proxy works only with local server
|
||||
if strings.Contains(setting.AppUrl, url[i+1:j]) {
|
||||
return setting.AppUrl + url[j+1:]
|
||||
} else {
|
||||
return "http://" + url[i+1:j] + "/" + url[j+1:]
|
||||
}
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
// RefId returns reference ID.
|
||||
func (sf *SubModuleFile) RefId() string {
|
||||
return sf.refId
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// Tag represents a Git tag.
|
||||
type Tag struct {
|
||||
Name string
|
||||
ID sha1
|
||||
repo *Repository
|
||||
Object sha1 // The id of this commit object
|
||||
Type string
|
||||
Tagger *Signature
|
||||
TagMessage string
|
||||
}
|
||||
|
||||
func (tag *Tag) Commit() (*Commit, error) {
|
||||
return tag.repo.getCommit(tag.Object)
|
||||
}
|
||||
|
||||
// Parse commit information from the (uncompressed) raw
|
||||
// data from the commit object.
|
||||
// \n\n separate headers from message
|
||||
func parseTagData(data []byte) (*Tag, error) {
|
||||
tag := new(Tag)
|
||||
// we now have the contents of the commit object. Let's investigate...
|
||||
nextline := 0
|
||||
l:
|
||||
for {
|
||||
eol := bytes.IndexByte(data[nextline:], '\n')
|
||||
switch {
|
||||
case eol > 0:
|
||||
line := data[nextline : nextline+eol]
|
||||
spacepos := bytes.IndexByte(line, ' ')
|
||||
reftype := line[:spacepos]
|
||||
switch string(reftype) {
|
||||
case "object":
|
||||
id, err := NewIdFromString(string(line[spacepos+1:]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tag.Object = id
|
||||
case "type":
|
||||
// A commit can have one or more parents
|
||||
tag.Type = string(line[spacepos+1:])
|
||||
case "tagger":
|
||||
sig, err := newSignatureFromCommitline(line[spacepos+1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tag.Tagger = sig
|
||||
}
|
||||
nextline += eol + 1
|
||||
case eol == 0:
|
||||
tag.TagMessage = string(data[nextline+1:])
|
||||
break l
|
||||
default:
|
||||
break l
|
||||
}
|
||||
}
|
||||
return tag, nil
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotExist = errors.New("error not exist")
|
||||
)
|
||||
|
||||
// A tree is a flat directory listing.
|
||||
type Tree struct {
|
||||
ID sha1
|
||||
repo *Repository
|
||||
|
||||
// parent tree
|
||||
ptree *Tree
|
||||
|
||||
entries Entries
|
||||
entriesParsed bool
|
||||
}
|
||||
|
||||
var escapeChar = []byte("\\")
|
||||
|
||||
func UnescapeChars(in []byte) []byte {
|
||||
if bytes.Index(in, escapeChar) == -1 {
|
||||
return in
|
||||
}
|
||||
|
||||
endIdx := len(in) - 1
|
||||
isEscape := false
|
||||
out := make([]byte, 0, endIdx+1)
|
||||
for i := range in {
|
||||
if in[i] == '\\' && !isEscape {
|
||||
isEscape = true
|
||||
continue
|
||||
}
|
||||
isEscape = false
|
||||
out = append(out, in[i])
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Parse tree information from the (uncompressed) raw
|
||||
// data from the tree object.
|
||||
func parseTreeData(tree *Tree, data []byte) ([]*TreeEntry, error) {
|
||||
entries := make([]*TreeEntry, 0, 10)
|
||||
l := len(data)
|
||||
pos := 0
|
||||
for pos < l {
|
||||
entry := new(TreeEntry)
|
||||
entry.ptree = tree
|
||||
step := 6
|
||||
switch string(data[pos : pos+step]) {
|
||||
case "100644":
|
||||
entry.mode = ModeBlob
|
||||
entry.Type = BLOB
|
||||
case "100755":
|
||||
entry.mode = ModeExec
|
||||
entry.Type = BLOB
|
||||
case "120000":
|
||||
entry.mode = ModeSymlink
|
||||
entry.Type = BLOB
|
||||
case "160000":
|
||||
entry.mode = ModeCommit
|
||||
entry.Type = COMMIT
|
||||
|
||||
step = 8
|
||||
case "040000":
|
||||
entry.mode = ModeTree
|
||||
entry.Type = TREE
|
||||
default:
|
||||
return nil, errors.New("unknown type: " + string(data[pos:pos+step]))
|
||||
}
|
||||
pos += step + 6 // Skip string type of entry type.
|
||||
|
||||
step = 40
|
||||
id, err := NewIdFromString(string(data[pos : pos+step]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entry.ID = id
|
||||
pos += step + 1 // Skip half of sha1.
|
||||
|
||||
step = bytes.IndexByte(data[pos:], '\n')
|
||||
|
||||
// In case entry name is surrounded by double quotes(it happens only in git-shell).
|
||||
if data[pos] == '"' {
|
||||
entry.name = string(UnescapeChars(data[pos+1 : pos+step-1]))
|
||||
} else {
|
||||
entry.name = string(data[pos : pos+step])
|
||||
}
|
||||
|
||||
pos += step + 1
|
||||
entries = append(entries, entry)
|
||||
}
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
func (t *Tree) SubTree(rpath string) (*Tree, error) {
|
||||
if len(rpath) == 0 {
|
||||
return t, nil
|
||||
}
|
||||
|
||||
paths := strings.Split(rpath, "/")
|
||||
var err error
|
||||
var g = t
|
||||
var p = t
|
||||
var te *TreeEntry
|
||||
for _, name := range paths {
|
||||
te, err = p.GetTreeEntryByPath(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g, err = t.repo.getTree(te.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g.ptree = p
|
||||
p = g
|
||||
}
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func (t *Tree) ListEntries(relpath string) (Entries, error) {
|
||||
if t.entriesParsed {
|
||||
return t.entries, nil
|
||||
}
|
||||
t.entriesParsed = true
|
||||
|
||||
stdout, stderr, err := com.ExecCmdDirBytes(t.repo.Path,
|
||||
"git", "ls-tree", t.ID.String())
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "exit status 128") {
|
||||
return nil, errors.New(strings.TrimSpace(string(stderr)))
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
t.entries, err = parseTreeData(t, stdout)
|
||||
return t.entries, err
|
||||
}
|
||||
|
||||
func NewTree(repo *Repository, id sha1) *Tree {
|
||||
tree := new(Tree)
|
||||
tree.ID = id
|
||||
tree.repo = repo
|
||||
return tree
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) {
|
||||
if len(relpath) == 0 {
|
||||
return &TreeEntry{
|
||||
ID: t.ID,
|
||||
Type: TREE,
|
||||
mode: ModeTree,
|
||||
}, nil
|
||||
// return nil, fmt.Errorf("GetTreeEntryByPath(empty relpath): %v", ErrNotExist)
|
||||
}
|
||||
|
||||
relpath = path.Clean(relpath)
|
||||
parts := strings.Split(relpath, "/")
|
||||
var err error
|
||||
tree := t
|
||||
for i, name := range parts {
|
||||
if i == len(parts)-1 {
|
||||
entries, err := tree.ListEntries(path.Dir(relpath))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range entries {
|
||||
if v.name == name {
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tree, err = tree.SubTree(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("GetTreeEntryByPath: %v", ErrNotExist)
|
||||
}
|
||||
|
||||
func (t *Tree) GetBlobByPath(rpath string) (*Blob, error) {
|
||||
entry, err := t.GetTreeEntryByPath(rpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !entry.IsDir() {
|
||||
return entry.Blob(), nil
|
||||
}
|
||||
|
||||
return nil, ErrNotExist
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
type EntryMode int
|
||||
|
||||
// There are only a few file modes in Git. They look like unix file modes, but they can only be
|
||||
// one of these.
|
||||
const (
|
||||
ModeBlob EntryMode = 0100644
|
||||
ModeExec EntryMode = 0100755
|
||||
ModeSymlink EntryMode = 0120000
|
||||
ModeCommit EntryMode = 0160000
|
||||
ModeTree EntryMode = 0040000
|
||||
)
|
||||
|
||||
type TreeEntry struct {
|
||||
ID sha1
|
||||
Type ObjectType
|
||||
|
||||
mode EntryMode
|
||||
name string
|
||||
|
||||
ptree *Tree
|
||||
|
||||
commited bool
|
||||
|
||||
size int64
|
||||
sized bool
|
||||
}
|
||||
|
||||
func (te *TreeEntry) Name() string {
|
||||
return te.name
|
||||
}
|
||||
|
||||
func (te *TreeEntry) Size() int64 {
|
||||
if te.IsDir() {
|
||||
return 0
|
||||
}
|
||||
|
||||
if te.sized {
|
||||
return te.size
|
||||
}
|
||||
|
||||
stdout, _, err := com.ExecCmdDir(te.ptree.repo.Path, "git", "cat-file", "-s", te.ID.String())
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
te.sized = true
|
||||
te.size = com.StrTo(strings.TrimSpace(stdout)).MustInt64()
|
||||
return te.size
|
||||
}
|
||||
|
||||
func (te *TreeEntry) IsSubModule() bool {
|
||||
return te.mode == ModeCommit
|
||||
}
|
||||
|
||||
func (te *TreeEntry) IsDir() bool {
|
||||
return te.mode == ModeTree
|
||||
}
|
||||
|
||||
func (te *TreeEntry) EntryMode() EntryMode {
|
||||
return te.mode
|
||||
}
|
||||
|
||||
func (te *TreeEntry) Blob() *Blob {
|
||||
return &Blob{
|
||||
repo: te.ptree.repo,
|
||||
TreeEntry: te,
|
||||
}
|
||||
}
|
||||
|
||||
type Entries []*TreeEntry
|
||||
|
||||
var sorter = []func(t1, t2 *TreeEntry) bool{
|
||||
func(t1, t2 *TreeEntry) bool {
|
||||
return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
|
||||
},
|
||||
func(t1, t2 *TreeEntry) bool {
|
||||
return t1.name < t2.name
|
||||
},
|
||||
}
|
||||
|
||||
func (bs Entries) Len() int { return len(bs) }
|
||||
func (bs Entries) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] }
|
||||
func (bs Entries) Less(i, j int) bool {
|
||||
t1, t2 := bs[i], bs[j]
|
||||
var k int
|
||||
for k = 0; k < len(sorter)-1; k++ {
|
||||
sort := sorter[k]
|
||||
switch {
|
||||
case sort(t1, t2):
|
||||
return true
|
||||
case sort(t2, t1):
|
||||
return false
|
||||
}
|
||||
}
|
||||
return sorter[k](t1, t2)
|
||||
}
|
||||
|
||||
func (bs Entries) Sort() {
|
||||
sort.Sort(bs)
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const prettyLogFormat = `--pretty=format:%H`
|
||||
|
||||
func parsePrettyFormatLog(repo *Repository, logByts []byte) (*list.List, error) {
|
||||
l := list.New()
|
||||
if len(logByts) == 0 {
|
||||
return l, nil
|
||||
}
|
||||
|
||||
parts := bytes.Split(logByts, []byte{'\n'})
|
||||
|
||||
for _, commitId := range parts {
|
||||
commit, err := repo.GetCommit(string(commitId))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l.PushBack(commit)
|
||||
}
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func RefEndName(refStr string) string {
|
||||
if strings.HasPrefix(refStr, "refs/heads/") {
|
||||
// trim the "refs/heads/"
|
||||
return refStr[len("refs/heads/"):]
|
||||
}
|
||||
|
||||
index := strings.LastIndex(refStr, "/")
|
||||
if index != -1 {
|
||||
return refStr[index+1:]
|
||||
}
|
||||
return refStr
|
||||
}
|
||||
|
||||
// If the object is stored in its own file (i.e not in a pack file),
|
||||
// this function returns the full path to the object file.
|
||||
// It does not test if the file exists.
|
||||
func filepathFromSHA1(rootdir, sha1 string) string {
|
||||
return filepath.Join(rootdir, "objects", sha1[:2], sha1[2:])
|
||||
}
|
||||
|
||||
// isDir returns true if given path is a directory,
|
||||
// or returns false when it's a file or does not exist.
|
||||
func isDir(dir string) bool {
|
||||
f, e := os.Stat(dir)
|
||||
if e != nil {
|
||||
return false
|
||||
}
|
||||
return f.IsDir()
|
||||
}
|
||||
|
||||
// isFile returns true if given path is a file,
|
||||
// or returns false when it's a directory or does not exist.
|
||||
func isFile(filePath string) bool {
|
||||
f, e := os.Stat(filePath)
|
||||
if e != nil {
|
||||
return false
|
||||
}
|
||||
return !f.IsDir()
|
||||
}
|
||||
|
||||
func concatenateError(err error, stderr string) error {
|
||||
if len(stderr) == 0 {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("%v: %s", err, stderr)
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package git
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
var (
|
||||
// Cached Git version.
|
||||
gitVer *Version
|
||||
)
|
||||
|
||||
// Version represents version of Git.
|
||||
type Version struct {
|
||||
Major, Minor, Patch int
|
||||
}
|
||||
|
||||
func ParseVersion(verStr string) (*Version, error) {
|
||||
infos := strings.Split(verStr, ".")
|
||||
if len(infos) < 3 {
|
||||
return nil, errors.New("incorrect version input")
|
||||
}
|
||||
|
||||
v := &Version{}
|
||||
for i, s := range infos {
|
||||
switch i {
|
||||
case 0:
|
||||
v.Major, _ = com.StrTo(s).Int()
|
||||
case 1:
|
||||
v.Minor, _ = com.StrTo(s).Int()
|
||||
case 2:
|
||||
v.Patch, _ = com.StrTo(strings.TrimSpace(s)).Int()
|
||||
}
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func MustParseVersion(verStr string) *Version {
|
||||
v, _ := ParseVersion(verStr)
|
||||
return v
|
||||
}
|
||||
|
||||
// Compare compares two versions,
|
||||
// it returns 1 if original is greater, -1 if original is smaller, 0 if equal.
|
||||
func (v *Version) Compare(that *Version) int {
|
||||
if v.Major > that.Major {
|
||||
return 1
|
||||
} else if v.Major < that.Major {
|
||||
return -1
|
||||
}
|
||||
|
||||
if v.Minor > that.Minor {
|
||||
return 1
|
||||
} else if v.Minor < that.Minor {
|
||||
return -1
|
||||
}
|
||||
|
||||
if v.Patch > that.Patch {
|
||||
return 1
|
||||
} else if v.Patch < that.Patch {
|
||||
return -1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (v *Version) LessThan(that *Version) bool {
|
||||
return v.Compare(that) < 0
|
||||
}
|
||||
|
||||
func (v *Version) AtLeast(that *Version) bool {
|
||||
return v.Compare(that) >= 0
|
||||
}
|
||||
|
||||
func (v *Version) String() string {
|
||||
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
|
||||
}
|
||||
|
||||
// GetVersion returns current Git version installed.
|
||||
func GetVersion() (*Version, error) {
|
||||
if gitVer != nil {
|
||||
return gitVer, nil
|
||||
}
|
||||
|
||||
stdout, stderr, err := com.ExecCmd("git", "version")
|
||||
if err != nil {
|
||||
return nil, errors.New(stderr)
|
||||
}
|
||||
|
||||
infos := strings.Split(stdout, " ")
|
||||
if len(infos) < 3 {
|
||||
return nil, errors.New("not enough output")
|
||||
}
|
||||
|
||||
gitVer, err = ParseVersion(infos[2])
|
||||
return gitVer, err
|
||||
}
|
||||
@@ -33,7 +33,7 @@ func NewLogger(bufLen int64, mode, config string) {
|
||||
loggers = append(loggers, logger)
|
||||
}
|
||||
if err := logger.SetLogger(mode, config); err != nil {
|
||||
Fatal(1, "Fail to set logger(%s): %v", mode, err)
|
||||
Fatal(2, "Fail to set logger (%s): %v", mode, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ func Toggle(options *ToggleOptions) macaron.Handler {
|
||||
ctx.Handle(500, "AutoSignIn", err)
|
||||
return
|
||||
} else if succeed {
|
||||
log.Trace("Auto-login succeed: %s", ctx.Session.Get("uname"))
|
||||
ctx.Redirect(setting.AppSubUrl + ctx.Req.RequestURI)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@ import (
|
||||
"github.com/go-macaron/session"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/auth"
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/git"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
@@ -29,9 +30,9 @@ import (
|
||||
type RepoContext struct {
|
||||
AccessMode models.AccessMode
|
||||
IsWatching bool
|
||||
IsBranch bool
|
||||
IsTag bool
|
||||
IsCommit bool
|
||||
IsViewBranch bool
|
||||
IsViewTag bool
|
||||
IsViewCommit bool
|
||||
Repository *models.Repository
|
||||
Owner *models.User
|
||||
Commit *git.Commit
|
||||
@@ -43,7 +44,7 @@ type RepoContext struct {
|
||||
CommitID string
|
||||
RepoLink string
|
||||
CloneLink models.CloneLink
|
||||
CommitsCount int
|
||||
CommitsCount int64
|
||||
Mirror *models.Mirror
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,9 @@ import (
|
||||
|
||||
"gopkg.in/macaron.v1"
|
||||
|
||||
"github.com/gogits/git-module"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/git"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
@@ -129,6 +130,7 @@ func RepoAssignment(args ...bool) macaron.Handler {
|
||||
return
|
||||
}
|
||||
ctx.Data["MirrorInterval"] = ctx.Repo.Mirror.Interval
|
||||
ctx.Data["Mirror"] = ctx.Repo.Mirror
|
||||
}
|
||||
|
||||
ctx.Repo.Repository = repo
|
||||
@@ -256,13 +258,13 @@ func RepoRef() macaron.Handler {
|
||||
}
|
||||
refName = brs[0]
|
||||
}
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfBranch(refName)
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "GetCommitOfBranch", err)
|
||||
ctx.Handle(500, "GetBranchCommit", err)
|
||||
return
|
||||
}
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
ctx.Repo.IsBranch = true
|
||||
ctx.Repo.IsViewBranch = true
|
||||
|
||||
} else {
|
||||
hasMatched := false
|
||||
@@ -285,25 +287,25 @@ func RepoRef() macaron.Handler {
|
||||
}
|
||||
|
||||
if ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
ctx.Repo.IsBranch = true
|
||||
ctx.Repo.IsViewBranch = true
|
||||
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfBranch(refName)
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "GetCommitOfBranch", err)
|
||||
ctx.Handle(500, "GetBranchCommit", err)
|
||||
return
|
||||
}
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
|
||||
} else if ctx.Repo.GitRepo.IsTagExist(refName) {
|
||||
ctx.Repo.IsTag = true
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfTag(refName)
|
||||
ctx.Repo.IsViewTag = true
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refName)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "GetCommitOfTag", err)
|
||||
ctx.Handle(500, "GetTagCommit", err)
|
||||
return
|
||||
}
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
} else if len(refName) == 40 {
|
||||
ctx.Repo.IsCommit = true
|
||||
ctx.Repo.IsViewCommit = true
|
||||
ctx.Repo.CommitID = refName
|
||||
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
|
||||
@@ -320,9 +322,9 @@ func RepoRef() macaron.Handler {
|
||||
ctx.Repo.BranchName = refName
|
||||
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
||||
ctx.Data["CommitID"] = ctx.Repo.CommitID
|
||||
ctx.Data["IsBranch"] = ctx.Repo.IsBranch
|
||||
ctx.Data["IsTag"] = ctx.Repo.IsTag
|
||||
ctx.Data["IsCommit"] = ctx.Repo.IsCommit
|
||||
ctx.Data["IsViewBranch"] = ctx.Repo.IsViewBranch
|
||||
ctx.Data["IsViewTag"] = ctx.Repo.IsViewTag
|
||||
ctx.Data["IsViewCommit"] = ctx.Repo.IsViewCommit
|
||||
|
||||
ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
|
||||
if err != nil {
|
||||
|
||||
15
modules/setting/miniwinsvc.go
Normal file
15
modules/setting/miniwinsvc.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// +build miniwinsvc
|
||||
|
||||
// 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 setting
|
||||
|
||||
import (
|
||||
_ "github.com/kardianos/minwinsvc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
SupportMiniWinService = true
|
||||
}
|
||||
@@ -43,11 +43,11 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// Build information.
|
||||
// Build information
|
||||
BuildTime string
|
||||
BuildGitHash string
|
||||
|
||||
// App settings.
|
||||
// App settings
|
||||
AppVer string
|
||||
AppName string
|
||||
AppUrl string
|
||||
@@ -55,10 +55,11 @@ var (
|
||||
AppPath string
|
||||
AppDataPath = "data"
|
||||
|
||||
// Server settings.
|
||||
// Server settings
|
||||
Protocol Scheme
|
||||
Domain string
|
||||
HttpAddr, HttpPort string
|
||||
LocalURL string
|
||||
DisableSSH bool
|
||||
StartSSHServer bool
|
||||
SSHDomain string
|
||||
@@ -70,7 +71,7 @@ var (
|
||||
EnableGzip bool
|
||||
LandingPageUrl LandingPage
|
||||
|
||||
// Security settings.
|
||||
// Security settings
|
||||
InstallLock bool
|
||||
SecretKey string
|
||||
LogInRememberDays int
|
||||
@@ -78,13 +79,13 @@ var (
|
||||
CookieRememberName string
|
||||
ReverseProxyAuthUser string
|
||||
|
||||
// Database settings.
|
||||
// Database settings
|
||||
UseSQLite3 bool
|
||||
UseMySQL bool
|
||||
UsePostgreSQL bool
|
||||
UseTiDB bool
|
||||
|
||||
// Webhook settings.
|
||||
// Webhook settings
|
||||
Webhook struct {
|
||||
QueueLength int
|
||||
DeliverTimeout int
|
||||
@@ -93,16 +94,17 @@ var (
|
||||
PagingNum int
|
||||
}
|
||||
|
||||
// Repository settings.
|
||||
// Repository settings
|
||||
Repository struct {
|
||||
AnsiCharset string
|
||||
ForcePrivate bool
|
||||
MaxCreationLimit int
|
||||
PullRequestQueueLength int
|
||||
}
|
||||
RepoRootPath string
|
||||
ScriptType string
|
||||
|
||||
// UI settings.
|
||||
// UI settings
|
||||
ExplorePagingNum int
|
||||
IssuePagingNum int
|
||||
FeedMaxCommitNum int
|
||||
@@ -111,47 +113,47 @@ var (
|
||||
AdminNoticePagingNum int
|
||||
AdminOrgPagingNum int
|
||||
|
||||
// Markdown sttings.
|
||||
// Markdown sttings
|
||||
Markdown struct {
|
||||
EnableHardLineBreak bool
|
||||
}
|
||||
|
||||
// Picture settings.
|
||||
// Picture settings
|
||||
PictureService string
|
||||
AvatarUploadPath string
|
||||
GravatarSource string
|
||||
DisableGravatar bool
|
||||
|
||||
// Log settings.
|
||||
// Log settings
|
||||
LogRootPath string
|
||||
LogModes []string
|
||||
LogConfigs []string
|
||||
|
||||
// Attachment settings.
|
||||
// Attachment settings
|
||||
AttachmentPath string
|
||||
AttachmentAllowedTypes string
|
||||
AttachmentMaxSize int64
|
||||
AttachmentMaxFiles int
|
||||
AttachmentEnabled bool
|
||||
|
||||
// Time settings.
|
||||
// Time settings
|
||||
TimeFormat string
|
||||
|
||||
// Cache settings.
|
||||
// Cache settings
|
||||
CacheAdapter string
|
||||
CacheInternal int
|
||||
CacheConn string
|
||||
|
||||
// Session settings.
|
||||
// Session settings
|
||||
SessionConfig session.Options
|
||||
|
||||
// Git settings.
|
||||
// Git settings
|
||||
Git struct {
|
||||
MaxGitDiffLines int
|
||||
GcArgs []string `delim:" "`
|
||||
}
|
||||
|
||||
// Cron tasks.
|
||||
// Cron tasks
|
||||
Cron struct {
|
||||
UpdateMirror struct {
|
||||
Enabled bool
|
||||
@@ -162,6 +164,7 @@ var (
|
||||
Enabled bool
|
||||
RunAtStart bool
|
||||
Schedule string
|
||||
Timeout time.Duration
|
||||
Args []string `delim:" "`
|
||||
} `ini:"cron.repo_health_check"`
|
||||
CheckRepoStats struct {
|
||||
@@ -171,17 +174,20 @@ var (
|
||||
} `ini:"cron.check_repo_stats"`
|
||||
}
|
||||
|
||||
// I18n settings.
|
||||
// I18n settings
|
||||
Langs, Names []string
|
||||
dateLangs map[string]string
|
||||
|
||||
// Other settings.
|
||||
ShowFooterBranding bool
|
||||
ShowFooterVersion bool
|
||||
// Highlight settings are loaded in modules/template/hightlight.go
|
||||
|
||||
// Global setting objects.
|
||||
// Other settings
|
||||
ShowFooterBranding bool
|
||||
ShowFooterVersion bool
|
||||
SupportMiniWinService bool
|
||||
|
||||
// Global setting objects
|
||||
Cfg *ini.File
|
||||
CustomPath string // Custom directory path.
|
||||
CustomPath string // Custom directory path
|
||||
CustomConf string
|
||||
ProdMode bool
|
||||
RunUser string
|
||||
@@ -299,6 +305,7 @@ func NewContext() {
|
||||
Domain = sec.Key("DOMAIN").MustString("localhost")
|
||||
HttpAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0")
|
||||
HttpPort = sec.Key("HTTP_PORT").MustString("3000")
|
||||
LocalURL = sec.Key("LOCAL_ROOT_URL").MustString("http://localhost:" + HttpPort + "/")
|
||||
DisableSSH = sec.Key("DISABLE_SSH").MustBool()
|
||||
if !DisableSSH {
|
||||
StartSSHServer = sec.Key("START_SSH_SERVER").MustBool()
|
||||
@@ -376,9 +383,9 @@ func NewContext() {
|
||||
RepoRootPath = path.Clean(RepoRootPath)
|
||||
}
|
||||
ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
|
||||
Repository.AnsiCharset = sec.Key("ANSI_CHARSET").String()
|
||||
Repository.ForcePrivate = sec.Key("FORCE_PRIVATE").MustBool()
|
||||
Repository.PullRequestQueueLength = sec.Key("PULL_REQUEST_QUEUE_LENGTH").MustInt(10000)
|
||||
if err = Cfg.Section("repository").MapTo(&Repository); err != nil {
|
||||
log.Fatal(4, "Fail to map Repository settings: %v", err)
|
||||
}
|
||||
|
||||
// UI settings.
|
||||
sec = Cfg.Section("ui")
|
||||
@@ -509,7 +516,10 @@ func newLogService() {
|
||||
LogConfigs[i] = fmt.Sprintf(`{"level":%s}`, level)
|
||||
case "file":
|
||||
logPath := sec.Key("FILE_NAME").MustString(path.Join(LogRootPath, "gogs.log"))
|
||||
os.MkdirAll(path.Dir(logPath), os.ModePerm)
|
||||
if err = os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
LogConfigs[i] = fmt.Sprintf(
|
||||
`{"level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d}`, level,
|
||||
logPath,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// +build go1.4
|
||||
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
@@ -53,7 +51,8 @@ func handleServerConn(keyID string, chans <-chan ssh.NewChannel) {
|
||||
case "env":
|
||||
args := strings.Split(strings.Replace(payload, "\x00", "", -1), "\v")
|
||||
if len(args) != 2 {
|
||||
return
|
||||
log.Warn("Invalid env arguments: '%#v'", args)
|
||||
continue
|
||||
}
|
||||
args[0] = strings.TrimLeft(args[0], "\x04")
|
||||
_, _, err := com.ExecCmdBytes("env", args[0]+"="+args[1])
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
// +build !go1.4
|
||||
|
||||
package ssh
|
||||
|
||||
func Listen(port int) {
|
||||
panic("Gogs requires Go 1.4 for starting a SSH server")
|
||||
}
|
||||
97
modules/template/highlight.go
Normal file
97
modules/template/highlight.go
Normal file
@@ -0,0 +1,97 @@
|
||||
// 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 template
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
var (
|
||||
// File name should ignore highlight.
|
||||
ignoreFileNames = map[string]bool{
|
||||
"license": true,
|
||||
"copying": true,
|
||||
}
|
||||
|
||||
// File names that are representing highlight classes.
|
||||
highlightFileNames = map[string]bool{
|
||||
"dockerfile": true,
|
||||
"makefile": true,
|
||||
}
|
||||
|
||||
// Extensions that are same as highlight classes.
|
||||
highlightExts = map[string]bool{
|
||||
".arm": true,
|
||||
".as": true,
|
||||
".sh": true,
|
||||
".cs": true,
|
||||
".cpp": true,
|
||||
".c": true,
|
||||
".css": true,
|
||||
".cmake": true,
|
||||
".bat": true,
|
||||
".dart": true,
|
||||
".patch": true,
|
||||
".elixir": true,
|
||||
".erlang": true,
|
||||
".go": true,
|
||||
".html": true,
|
||||
".xml": true,
|
||||
".hs": true,
|
||||
".ini": true,
|
||||
".json": true,
|
||||
".java": true,
|
||||
".js": true,
|
||||
".less": true,
|
||||
".lua": true,
|
||||
".php": true,
|
||||
".py": true,
|
||||
".rb": true,
|
||||
".scss": true,
|
||||
".sql": true,
|
||||
".scala": true,
|
||||
".swift": true,
|
||||
".ts": true,
|
||||
".vb": true,
|
||||
}
|
||||
|
||||
// Extensions that are not same as highlight classes.
|
||||
highlightMapping = map[string]string{}
|
||||
)
|
||||
|
||||
func NewContext() {
|
||||
keys := setting.Cfg.Section("highlight.mapping").Keys()
|
||||
for i := range keys {
|
||||
highlightMapping[keys[i].Name()] = keys[i].Value()
|
||||
}
|
||||
}
|
||||
|
||||
// FileNameToHighlightClass returns the best match for highlight class name
|
||||
// based on the rule of highlight.js.
|
||||
func FileNameToHighlightClass(fname string) string {
|
||||
fname = strings.ToLower(fname)
|
||||
if ignoreFileNames[fname] {
|
||||
return "nohighlight"
|
||||
}
|
||||
|
||||
if highlightFileNames[fname] {
|
||||
return fname
|
||||
}
|
||||
|
||||
ext := path.Ext(fname)
|
||||
if highlightExts[ext] {
|
||||
return ext[1:]
|
||||
}
|
||||
|
||||
name, ok := highlightMapping[ext]
|
||||
if ok {
|
||||
return name
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
@@ -34,6 +34,9 @@ var Funcs template.FuncMap = map[string]interface{}{
|
||||
"AppSubUrl": func() string {
|
||||
return setting.AppSubUrl
|
||||
},
|
||||
"AppUrl": func() string {
|
||||
return setting.AppUrl
|
||||
},
|
||||
"AppVer": func() string {
|
||||
return setting.AppVer
|
||||
},
|
||||
@@ -127,11 +130,7 @@ func Sha1(str string) string {
|
||||
}
|
||||
|
||||
func ToUtf8WithErr(content []byte) (error, string) {
|
||||
charsetLabel, err := base.DetectEncoding(content)
|
||||
if err != nil {
|
||||
return err, ""
|
||||
}
|
||||
|
||||
charsetLabel := base.DetectEncoding(content)
|
||||
if charsetLabel == "UTF-8" {
|
||||
return nil, string(content)
|
||||
}
|
||||
@@ -183,15 +182,27 @@ func ReplaceLeft(s, old, new string) string {
|
||||
}
|
||||
|
||||
// RenderCommitMessage renders commit message with XSS-safe and special links.
|
||||
func RenderCommitMessage(msg, urlPrefix string, metas map[string]string) template.HTML {
|
||||
func RenderCommitMessage(full bool, msg, urlPrefix string, metas map[string]string) template.HTML {
|
||||
cleanMsg := template.HTMLEscapeString(msg)
|
||||
fullMessage := string(base.RenderIssueIndexPattern([]byte(cleanMsg), urlPrefix, metas))
|
||||
msgLines := strings.Split(strings.TrimSpace(fullMessage), "\n")
|
||||
for i := range msgLines {
|
||||
msgLines[i] = ReplaceLeft(msgLines[i], " ", " ")
|
||||
numLines := len(msgLines)
|
||||
if numLines == 0 {
|
||||
return template.HTML("")
|
||||
} else if !full {
|
||||
return template.HTML(msgLines[0])
|
||||
} else if numLines == 1 || (numLines >= 2 && len(msgLines[1]) == 0) {
|
||||
// First line is a header, standalone or followed by empty line
|
||||
header := fmt.Sprintf("<h3>%s</h3>", msgLines[0])
|
||||
if numLines >= 2 {
|
||||
fullMessage = header + fmt.Sprintf("\n<pre>%s</pre>", strings.Join(msgLines[2:], "\n"))
|
||||
} else {
|
||||
fullMessage = header
|
||||
}
|
||||
} else {
|
||||
// Non-standard git message, there is no header line
|
||||
fullMessage = fmt.Sprintf("<h4>%s</h4>", strings.Join(msgLines, "<br>"))
|
||||
}
|
||||
|
||||
fullMessage = strings.Join(msgLines, "<br>")
|
||||
return template.HTML(fullMessage)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
APP_NAME="gogs"
|
||||
CLI="${APP_NAME}"
|
||||
APP_USER=$(${CLI} config:get APP_USER)
|
||||
APP_GROUP=$(${CLI} config:get APP_GROUP)
|
||||
APP_CONFIG="/etc/${APP_NAME}/conf/app.ini"
|
||||
|
||||
case "$1" in
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
exit 0
|
||||
;;
|
||||
|
||||
configure|*)
|
||||
mkdir -p $(dirname ${APP_CONFIG})
|
||||
chown ${APP_USER}.${APP_GROUP} $(dirname ${APP_CONFIG})
|
||||
[ -f ${APP_CONFIG} ] || ${CLI} run cp conf/app.ini ${APP_CONFIG}
|
||||
${CLI} config:set USER=${APP_USER}
|
||||
sed -i "s|RUN_USER = git|RUN_USER = ${APP_USER}|" ${APP_CONFIG}
|
||||
sed -i "s|RUN_MODE = dev|RUN_MODE = prod|" ${APP_CONFIG}
|
||||
|
||||
# setup symlink towards custom conf
|
||||
mkdir -p /opt/${APP_NAME}/custom/conf
|
||||
chown -R ${APP_USER}.${APP_GROUP} /opt/${APP_NAME}/custom
|
||||
ln -f -s ${APP_CONFIG} /opt/${APP_NAME}/custom/conf/app.ini
|
||||
|
||||
# scale
|
||||
${CLI} scale web=1 || true
|
||||
|
||||
# restart the service
|
||||
service gogs restart || true
|
||||
|
||||
;;
|
||||
|
||||
esac
|
||||
24
packager/hooks/postinst
Executable file
24
packager/hooks/postinst
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
APP_NAME="gogs"
|
||||
CLI="${APP_NAME}"
|
||||
APP_USER=$(${CLI} config:get APP_USER)
|
||||
APP_GROUP=$(${CLI} config:get APP_GROUP)
|
||||
APP_CONFIG="/etc/${APP_NAME}/conf/app.ini"
|
||||
|
||||
mkdir -p $(dirname ${APP_CONFIG})
|
||||
chown ${APP_USER}.${APP_GROUP} $(dirname ${APP_CONFIG})
|
||||
[ -f ${APP_CONFIG} ] || ${CLI} run cp conf/app.ini ${APP_CONFIG}
|
||||
${CLI} config:set USER=${APP_USER}
|
||||
sed -i "s|RUN_USER = git|RUN_USER = ${APP_USER}|" ${APP_CONFIG}
|
||||
sed -i "s|RUN_MODE = dev|RUN_MODE = prod|" ${APP_CONFIG}
|
||||
|
||||
${CLI} config:set GOGS_CUSTOM=/etc/${APP_NAME}
|
||||
|
||||
# scale
|
||||
${CLI} scale web=1 || true
|
||||
|
||||
# restart the service
|
||||
service gogs restart || true
|
||||
@@ -47,20 +47,20 @@
|
||||
"outputPathIsOutsideProject": 0,
|
||||
"outputPathIsSetByUser": 0
|
||||
},
|
||||
"\/css\/highlight-8.9.1\/default.css": {
|
||||
"\/css\/highlight-9.0.0\/default.css": {
|
||||
"fileType": 16,
|
||||
"ignore": 0,
|
||||
"ignoreWasSetByUser": 0,
|
||||
"inputAbbreviatedPath": "\/css\/highlight-8.9.1\/default.css",
|
||||
"inputAbbreviatedPath": "\/css\/highlight-9.0.0\/default.css",
|
||||
"outputAbbreviatedPath": "No Output Path",
|
||||
"outputPathIsOutsideProject": 0,
|
||||
"outputPathIsSetByUser": 0
|
||||
},
|
||||
"\/css\/highlight-8.9.1\/github.css": {
|
||||
"\/css\/highlight-9.0.0\/github.css": {
|
||||
"fileType": 16,
|
||||
"ignore": 0,
|
||||
"ignoreWasSetByUser": 0,
|
||||
"inputAbbreviatedPath": "\/css\/highlight-8.9.1\/github.css",
|
||||
"inputAbbreviatedPath": "\/css\/highlight-9.0.0\/github.css",
|
||||
"outputAbbreviatedPath": "No Output Path",
|
||||
"outputPathIsOutsideProject": 0,
|
||||
"outputPathIsSetByUser": 0
|
||||
|
||||
@@ -895,12 +895,21 @@ pre.raw {
|
||||
.ui .warning.segment {
|
||||
border-color: #F0C36D;
|
||||
}
|
||||
.ui .info.header {
|
||||
background-color: #d9edf7 !important;
|
||||
border-color: #85c5e5;
|
||||
}
|
||||
.ui .info.segment {
|
||||
border-color: #85c5e5;
|
||||
border: 1px solid #c5d5dd;
|
||||
}
|
||||
.ui .info.segment.top {
|
||||
background-color: #e6f1f6 !important;
|
||||
}
|
||||
.ui .info.segment.top h3,
|
||||
.ui .info.segment.top h4 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ui .info.segment.top h3:last-child {
|
||||
margin-top: 4px;
|
||||
}
|
||||
.ui .info.segment.top > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.ui .normal.header {
|
||||
font-weight: normal;
|
||||
@@ -1088,7 +1097,7 @@ footer .container .links > *:first-child {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.markdown.file-view {
|
||||
padding: 5px 2em 2em !important;
|
||||
padding: 2em 2em 2em !important;
|
||||
}
|
||||
.markdown > *:first-child {
|
||||
margin-top: 0 !important;
|
||||
@@ -1127,6 +1136,14 @@ footer .container .links > *:first-child {
|
||||
font-weight: bold;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.markdown h1:first-of-type,
|
||||
.markdown h2:first-of-type,
|
||||
.markdown h3:first-of-type,
|
||||
.markdown h4:first-of-type,
|
||||
.markdown h5:first-of-type,
|
||||
.markdown h6:first-of-type {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
.markdown h1 .octicon-link,
|
||||
.markdown h2 .octicon-link,
|
||||
.markdown h3 .octicon-link,
|
||||
@@ -1294,7 +1311,7 @@ footer .container .links > *:first-child {
|
||||
.markdown table th,
|
||||
.markdown table td {
|
||||
padding: 6px 13px !important;
|
||||
border: 1px solid #ddd;
|
||||
border: 1px solid #ddd !important;
|
||||
}
|
||||
.markdown table tr {
|
||||
background-color: #fff;
|
||||
@@ -1764,9 +1781,9 @@ footer .container .links > *:first-child {
|
||||
}
|
||||
.repository .head .fork-flag {
|
||||
margin-left: 38px;
|
||||
margin-top: 3px;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
line-height: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.repository .navbar .ui.label {
|
||||
@@ -1891,8 +1908,8 @@ footer .container .links > *:first-child {
|
||||
padding: 5px 5px 0 5px;
|
||||
}
|
||||
.repository.file.list #file-content .code-view * {
|
||||
font-size: 13px;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
line-height: 20px;
|
||||
}
|
||||
.repository.file.list #file-content .code-view table {
|
||||
@@ -1906,7 +1923,6 @@ footer .container .links > *:first-child {
|
||||
width: 1%;
|
||||
}
|
||||
.repository.file.list #file-content .code-view .lines-num span {
|
||||
font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
|
||||
line-height: 20px;
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
@@ -2301,11 +2317,11 @@ footer .container .links > *:first-child {
|
||||
color: #888;
|
||||
}
|
||||
.repository .diff-file-box .header {
|
||||
border-bottom: 1px solid #d4d4d5!important;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
.repository .diff-file-box .file-body.file-code .lines-num {
|
||||
text-align: right;
|
||||
color: #999;
|
||||
color: #A7A7A7;
|
||||
background: #fafafa;
|
||||
width: 1%;
|
||||
}
|
||||
@@ -2313,15 +2329,15 @@ footer .container .links > *:first-child {
|
||||
border-right: 1px solid #DDD;
|
||||
}
|
||||
.repository .diff-file-box .code-diff {
|
||||
font-size: 13px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.repository .diff-file-box .code-diff td {
|
||||
padding: 0;
|
||||
padding-left: 10px;
|
||||
border-top: none;
|
||||
}
|
||||
.repository .diff-file-box .code-diff pre {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
.repository .diff-file-box .code-diff .lines-num {
|
||||
border-right: 1px solid #d4d4d5;
|
||||
@@ -2329,25 +2345,20 @@ footer .container .links > *:first-child {
|
||||
}
|
||||
.repository .diff-file-box .code-diff tbody tr.tag-code td,
|
||||
.repository .diff-file-box .code-diff tbody tr.tag-code pre {
|
||||
background-color: #E0E0E0 !important;
|
||||
border-color: #ADADAD!important;
|
||||
background-color: #F0F0F0 !important;
|
||||
border-color: #D2CECE!important;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
.repository .diff-file-box .code-diff tbody tr.del-code td,
|
||||
.repository .diff-file-box .code-diff tbody tr.del-code pre {
|
||||
background-color: #ffe2dd !important;
|
||||
border-color: #e9aeae !important;
|
||||
background-color: #ffecec !important;
|
||||
border-color: #f1c0c0 !important;
|
||||
}
|
||||
.repository .diff-file-box .code-diff tbody tr.add-code td,
|
||||
.repository .diff-file-box .code-diff tbody tr.add-code pre {
|
||||
background-color: #d1ffd6 !important;
|
||||
border-color: #b4e2b4 !important;
|
||||
}
|
||||
.repository .diff-file-box .code-diff tbody tr:hover td {
|
||||
background-color: #FFF8D2 !important;
|
||||
border-color: #F0DB88 !important;
|
||||
}
|
||||
.repository .diff-file-box .code-diff tbody tr:hover pre {
|
||||
background-color: transparent !important;
|
||||
background-color: #eaffea !important;
|
||||
border-color: #c1e9c1 !important;
|
||||
}
|
||||
.repository .diff-file-box.file-content img {
|
||||
max-width: 100%;
|
||||
@@ -2764,7 +2775,6 @@ footer .container .links > *:first-child {
|
||||
width: 50%!important;
|
||||
}
|
||||
.organization.options input {
|
||||
width: 50%!important;
|
||||
min-width: 300px;
|
||||
}
|
||||
.organization.profile #org-avatar {
|
||||
@@ -2972,6 +2982,10 @@ footer .container .links > *:first-child {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.feeds .list .header .plus.icon {
|
||||
margin-top: 5px;
|
||||
margin-right: 0;
|
||||
}
|
||||
.feeds .list ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
|
||||
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #333;
|
||||
background: #f8f8f8;
|
||||
-webkit-text-size-adjust: none;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.diff .hljs-header {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.css .rule .hljs-keyword,
|
||||
.hljs-winutils,
|
||||
.nginx .hljs-title,
|
||||
.hljs-subst,
|
||||
.hljs-request,
|
||||
.hljs-status {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-hexcolor,
|
||||
.ruby .hljs-constant {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-tag .hljs-value,
|
||||
.hljs-doctag,
|
||||
.tex .hljs-formula {
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-id,
|
||||
.scss .hljs-preprocessor {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-list .hljs-keyword,
|
||||
.hljs-subst {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-type,
|
||||
.vhdl .hljs-literal,
|
||||
.tex .hljs-command {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-tag,
|
||||
.hljs-tag .hljs-title,
|
||||
.hljs-rule .hljs-property,
|
||||
.django .hljs-tag .hljs-keyword {
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-attribute,
|
||||
.hljs-variable,
|
||||
.lisp .hljs-body,
|
||||
.hljs-name {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.hljs-regexp {
|
||||
color: #009926;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.ruby .hljs-symbol .hljs-string,
|
||||
.lisp .hljs-keyword,
|
||||
.clojure .hljs-keyword,
|
||||
.scheme .hljs-keyword,
|
||||
.tex .hljs-special,
|
||||
.hljs-prompt {
|
||||
color: #990073;
|
||||
}
|
||||
|
||||
.hljs-built_in {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-preprocessor,
|
||||
.hljs-pragma,
|
||||
.hljs-pi,
|
||||
.hljs-doctype,
|
||||
.hljs-shebang,
|
||||
.hljs-cdata {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background: #fdd;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background: #dfd;
|
||||
}
|
||||
|
||||
.diff .hljs-change {
|
||||
background: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-chunk {
|
||||
color: #aaa;
|
||||
}
|
||||
99
public/css/highlight-9.0.0/github.css
Normal file
99
public/css/highlight-9.0.0/github.css
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
|
||||
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
color: #333;
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #998;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-subst {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-literal,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-tag .hljs-attr {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-doctag {
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-selector-id {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-subst {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-type,
|
||||
.hljs-class .hljs-title {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-attribute {
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-regexp,
|
||||
.hljs-link {
|
||||
color: #009926;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #990073;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-meta {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background: #fdd;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background: #dfd;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -218,8 +218,9 @@ function initRepository() {
|
||||
});
|
||||
}
|
||||
|
||||
// File list
|
||||
if ($('.repository.file.list').length > 0) {
|
||||
// File list and commits
|
||||
if ($('.repository.file.list').length > 0 ||
|
||||
('.repository.commits').length > 0) {
|
||||
initFilterSearchDropdown('.choose.reference .dropdown');
|
||||
|
||||
$('.reference.column').click(function () {
|
||||
@@ -410,7 +411,7 @@ function initRepository() {
|
||||
$status_btn.click(function () {
|
||||
$('#status').val($status_btn.data('status-val'));
|
||||
$('#comment-form').submit();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// Diff
|
||||
@@ -463,10 +464,7 @@ function initWiki() {
|
||||
element: $edit_area[0],
|
||||
previewRender: function (plainText, preview) { // Async method
|
||||
setTimeout(function () {
|
||||
if ($('.editor-preview-active').length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: still send render request when return back to edit mode
|
||||
$.post($edit_area.data('url'), {
|
||||
"_csrf": csrf,
|
||||
"mode": "gfm",
|
||||
@@ -869,7 +867,8 @@ $(document).ready(function () {
|
||||
|
||||
// Emojify
|
||||
emojify.setConfig({
|
||||
img_dir: suburl + '/img/emoji'
|
||||
img_dir: suburl + '/img/emoji',
|
||||
ignore_emoticons: true
|
||||
});
|
||||
emojify.run();
|
||||
|
||||
@@ -1036,4 +1035,4 @@ $(window).load(function () {
|
||||
}
|
||||
}).trigger('hashchange');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because one or more lines are too long
4
public/js/libs/highlight-9.0.0.pack.js
Normal file
4
public/js/libs/highlight-9.0.0.pack.js
Normal file
File diff suppressed because one or more lines are too long
@@ -11,7 +11,7 @@
|
||||
|
||||
thead {
|
||||
th:last-child {
|
||||
padding-right: 5px !important;
|
||||
padding-right: 5px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,9 +39,9 @@
|
||||
max-width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
dl.admin-dl-horizontal {
|
||||
padding: 20px;
|
||||
|
||||
dl.admin-dl-horizontal {
|
||||
padding: 20px;
|
||||
margin: 0;
|
||||
|
||||
dd{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@footer-margin: 40px;
|
||||
|
||||
|
||||
body {
|
||||
font-family: 'Helvetica Neue',Arial,Helvetica,sans-serif,'微软雅黑';
|
||||
background-color: #FAFAFA;
|
||||
@@ -10,20 +10,20 @@ img {
|
||||
pre {
|
||||
font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
&.raw {
|
||||
padding: 7px 12px;
|
||||
margin: 10px 0;
|
||||
background-color: #f8f8f8;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
overflow: auto;
|
||||
padding: 7px 12px;
|
||||
margin: 10px 0;
|
||||
background-color: #f8f8f8;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 3px;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
.full.height {
|
||||
padding: 0;
|
||||
margin: 0 0 -@footer-margin*2 0;
|
||||
min-height: 100%;
|
||||
margin: 0 0 -@footer-margin*2 0;
|
||||
min-height: 100%;
|
||||
}
|
||||
.following.bar {
|
||||
z-index: 900;
|
||||
@@ -65,24 +65,24 @@ pre {
|
||||
margin-right: 0;
|
||||
}
|
||||
.searchbox {
|
||||
background-color: rgb(244, 244, 244) !important;
|
||||
&:focus {
|
||||
background-color: rgb(233, 233, 233) !important;
|
||||
}
|
||||
background-color: rgb(244, 244, 244) !important;
|
||||
&:focus {
|
||||
background-color: rgb(233, 233, 233) !important;
|
||||
}
|
||||
}
|
||||
.text .octicon {
|
||||
width: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
.right.menu {
|
||||
.menu {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
width: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
.right.menu {
|
||||
.menu {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
.dropdown .menu {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ui {
|
||||
@@ -96,21 +96,21 @@ pre {
|
||||
.text {
|
||||
&.red {
|
||||
color: #d95c5c !important;
|
||||
a {
|
||||
color: #d95c5c !important;
|
||||
&:hover {
|
||||
color: #E67777 !important;
|
||||
}
|
||||
}
|
||||
a {
|
||||
color: #d95c5c !important;
|
||||
&:hover {
|
||||
color: #E67777 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.blue {
|
||||
color: #428bca !important;
|
||||
a {
|
||||
color: #15c !important;
|
||||
&:hover {
|
||||
color: #428bca !important;
|
||||
}
|
||||
}
|
||||
a {
|
||||
color: #15c !important;
|
||||
&:hover {
|
||||
color: #428bca !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.black {
|
||||
color: #444;
|
||||
@@ -119,13 +119,13 @@ pre {
|
||||
}
|
||||
}
|
||||
&.grey {
|
||||
color: #767676 !important;
|
||||
a {
|
||||
color: #444 !important;
|
||||
&:hover {
|
||||
color: #000 !important;
|
||||
}
|
||||
}
|
||||
color: #767676 !important;
|
||||
a {
|
||||
color: #444 !important;
|
||||
&:hover {
|
||||
color: #000 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.light.grey {
|
||||
color: #888 !important;
|
||||
@@ -189,19 +189,27 @@ pre {
|
||||
.warning {
|
||||
&.header {
|
||||
background-color: #F9EDBE !important;
|
||||
border-color: #F0C36D;
|
||||
border-color: #F0C36D;
|
||||
}
|
||||
&.segment {
|
||||
border-color: #F0C36D;
|
||||
border-color: #F0C36D;
|
||||
}
|
||||
}
|
||||
.info {
|
||||
&.header {
|
||||
background-color: #d9edf7 !important;
|
||||
border-color: #85c5e5;
|
||||
}
|
||||
&.segment {
|
||||
border-color: #85c5e5;
|
||||
border: 1px solid #c5d5dd;
|
||||
&.top {
|
||||
background-color: #e6f1f6 !important;
|
||||
h3, h4 {
|
||||
margin-top: 0;
|
||||
}
|
||||
h3:last-child {
|
||||
margin-top: 4px;
|
||||
}
|
||||
> :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,9 +269,9 @@ pre {
|
||||
font-weight: 700;
|
||||
}
|
||||
&:hover {
|
||||
background: rgba(0,0,0,.05);
|
||||
color: rgba(0,0,0,.8);
|
||||
z-index: 13;
|
||||
background: rgba(0,0,0,.05);
|
||||
color: rgba(0,0,0,.8);
|
||||
z-index: 13;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,7 +279,7 @@ pre {
|
||||
|
||||
.scrolling.menu {
|
||||
.item.selected {
|
||||
font-weight: 700 !important;
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,8 +295,8 @@ footer {
|
||||
padding-top: 10px;
|
||||
.fa {
|
||||
width: 16px;
|
||||
text-align: center;
|
||||
color: #428bca;
|
||||
text-align: center;
|
||||
color: #428bca;
|
||||
}
|
||||
.links >* {
|
||||
border-left: 1px solid #d6d6d6;
|
||||
@@ -310,11 +318,11 @@ footer {
|
||||
|
||||
.generate-img(16);
|
||||
.generate-img(@n, @i: 1) when (@i =< @n) {
|
||||
.img-@{i} {
|
||||
width: (2px * @i) !important;
|
||||
height: (2px * @i) !important;
|
||||
}
|
||||
.generate-img(@n, (@i + 1));
|
||||
.img-@{i} {
|
||||
width: (2px * @i) !important;
|
||||
height: (2px * @i) !important;
|
||||
}
|
||||
.generate-img(@n, (@i + 1));
|
||||
}
|
||||
|
||||
// ensure Semantic UI .icon font family and 14px size does not apply to .icon.octicon
|
||||
@@ -327,27 +335,27 @@ footer {
|
||||
|
||||
// Accessibility
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
border: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
border: 0;
|
||||
}
|
||||
.sr-only-focusable:active,
|
||||
.sr-only-focusable:focus {
|
||||
position: static;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
clip: auto;
|
||||
position: static;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
clip: auto;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 991px) and (min-width: 768px) {
|
||||
.ui.container {
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
z-index: 101;
|
||||
min-width: 200px;
|
||||
.ui.header {
|
||||
font-size: 1rem;
|
||||
text-transform: none;
|
||||
font-size: 1rem;
|
||||
text-transform: none;
|
||||
}
|
||||
}
|
||||
.filter.menu {
|
||||
@@ -17,8 +17,8 @@
|
||||
text-align: left;
|
||||
.text {
|
||||
height: 16px;
|
||||
vertical-align: middle;
|
||||
&.truncate {
|
||||
vertical-align: middle;
|
||||
&.truncate {
|
||||
width: 85%;
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@
|
||||
// Sort
|
||||
.jump.item {
|
||||
margin: 1px;
|
||||
padding-right: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
.menu {
|
||||
max-height: 300px;
|
||||
@@ -89,6 +89,11 @@
|
||||
.header {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 5px;
|
||||
|
||||
.plus.icon {
|
||||
margin-top: 5px;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
ul {
|
||||
list-style: none;
|
||||
@@ -96,24 +101,24 @@
|
||||
padding-left: 0;
|
||||
|
||||
li {
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid #EAEAEA;
|
||||
}
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid #EAEAEA;
|
||||
}
|
||||
|
||||
&.private {
|
||||
background-color: #fcf8e9;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 6px 1.2em;
|
||||
display: block;
|
||||
|
||||
.octicon {
|
||||
margin-right: 6px;
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
a {
|
||||
padding: 6px 1.2em;
|
||||
display: block;
|
||||
|
||||
.octicon {
|
||||
margin-right: 6px;
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.emoji {
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
display: inline-block;
|
||||
background-size: contain;
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
display: inline-block;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
}
|
||||
}
|
||||
.time {
|
||||
font-size: 12px;
|
||||
color: #808080;
|
||||
font-size: 12px;
|
||||
color: #808080;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,4 +110,4 @@
|
||||
padding-left: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
}
|
||||
.octicon {
|
||||
color: #d9453d;
|
||||
font-size: 40px;
|
||||
width: 50px;
|
||||
font-size: 40px;
|
||||
width: 50px;
|
||||
}
|
||||
&.header {
|
||||
font-size: 20px;
|
||||
@@ -36,4 +36,4 @@
|
||||
.signup {
|
||||
padding-top: 15px;
|
||||
padding-bottom: @footer-margin * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,4 +28,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user