diff options
89 files changed, 1461 insertions, 835 deletions
@@ -1,6 +1,7 @@ .DS_Store *.db *.log +log/ custom/ data/ .vendor/ @@ -34,4 +35,4 @@ docker/fig.yml docker/docker/Dockerfile docker/docker/init_gogs.sh gogs.sublime-project -gogs.sublime-workspace
\ No newline at end of file +gogs.sublime-workspace @@ -2,32 +2,34 @@ path = github.com/gogits/gogs [deps] -github.com/beego/memcache = commit:2aea774416 +github.com/bradfitz/gomemcache = commit:72a68649ba github.com/Unknwon/cae = commit:2e70a1351b -github.com/Unknwon/com = commit:d9bcf409c8 +github.com/Unknwon/com = commit:188d690b1a github.com/Unknwon/i18n = commit:1e88666229 -github.com/Unknwon/macaron = -github.com/codegangsta/cli = commit:a14c5b47c7 -github.com/go-sql-driver/mysql = commit:04cf947760 -github.com/go-xorm/core = commit:e7882d8b00 -github.com/go-xorm/xorm = commit:dcc529b68a +github.com/Unknwon/macaron = commit:e089393c3f +github.com/codegangsta/cli = commit:6086d7927e +github.com/go-sql-driver/mysql = commit:27633f0519 +github.com/go-xorm/core = commit:16cb27928f +github.com/go-xorm/xorm = commit:f2d3be988e github.com/gogits/chardet = commit:2404f77725 github.com/gogits/go-gogs-client = commit:92e76d616a -github.com/lib/pq = commit:3e3efe51a0 -github.com/macaron-contrib/binding = commit:0fbe4b9707 -github.com/macaron-contrib/cache = -github.com/macaron-contrib/captcha = commit:3567dc48b8 -github.com/macaron-contrib/csrf = commit:3ea14e7ee7 -github.com/macaron-contrib/i18n = commit:0ee0539c84 +github.com/lib/pq = commit:835d5eb08d +github.com/macaron-contrib/binding = commit:dc739fabc3 +github.com/macaron-contrib/cache = commit:b68f6b448f +github.com/macaron-contrib/captcha = commit:066c50c7eb +github.com/macaron-contrib/csrf = commit:98ddf5a710 +github.com/macaron-contrib/i18n = commit:eeebd44f64 github.com/macaron-contrib/oauth2 = commit:8f394c3629 -github.com/macaron-contrib/session = -github.com/macaron-contrib/toolbox = commit:57127bcc89 -github.com/mattn/go-sqlite3 = commit:a80c27ba33 -github.com/microcosm-cc/bluemonday = +github.com/macaron-contrib/session = commit:8e8d938b27 +github.com/macaron-contrib/toolbox = commit:acbfe36e16 +github.com/mattn/go-sqlite3 = commit:25d045f12a +github.com/microcosm-cc/bluemonday = commit:fcd0f5074e github.com/nfnt/resize = commit:8f44931448 -github.com/russross/blackfriday = commit:05b8cefd6a -github.com/shurcooL/go = commit:48293cbc7a -gopkg.in/ini.v1 = commit:28ad8c408b +github.com/russross/blackfriday = commit:77efab57b2 +github.com/shurcooL/go = commit:329f57438c +golang.org/x/net = +golang.org/x/text = +gopkg.in/ini.v1 = commit:4febc4104c gopkg.in/redis.v2 = commit:e617904962 [res] diff --git a/.travis.yml b/.travis.yml index 85e5f396..4149e173 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,4 +12,5 @@ script: go build -v notifications: email: - - u@gogs.io
\ No newline at end of file + - u@gogs.io + slack: gophercn:o5pSanyTeNhnfYc3QnG0X7Wx
\ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d3619018..411a8e93 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,20 +2,20 @@ > This guidelines sheet is forked from [CONTRIBUTING.md](https://github.com/drone/drone/blob/master/CONTRIBUTING.md). -Gogs is not perfect and it has bugs, or incomplete features for rare cases. You're welcome to tell us or contribute some code. This document describes details about how can you contribute to Gogs project. +Gogs is not perfect, and it has bugs or incomplete features in rare cases. You're welcome to tell us, or to contribute some code. This document describes details about how can you contribute to Gogs project. ## Contribution guidelines Depends on the situation, you will: -- Find bug, create an issue -- Need more functionality, make a feature request -- Want to contribute code, open a pull request -- Run into issue, need help +- Find a bug and create an issue +- Need more functionality and make a feature request +- Want to contribute code and open a pull request +- Run into issue and need help ### Bug Report -If you find or consider something is a bug, please create a issue on [GitHub](https://github.com/gogits/gogs/issues). To reduce unnecessary time wasting of interacting and waiting with team members, please include following information in the first place with a comfortable form for you: +If you find something you consider a bug, please create a issue on [GitHub](https://github.com/gogits/gogs/issues). To avoid wasting time and reduce back-and-forth communication with team members, please include at least the following information in a form comfortable for you: - Bug Description - Gogs Version @@ -28,7 +28,7 @@ Please take a moment to check that an issue on [GitHub](https://github.com/gogit #### Bug Report Example -Gogs crashed when create repository with license, using v0.5.13.0207, SQLite3, Git 1.9.0, Ubuntu 12.04. +Gogs crashed when creating a repository with a license, using v0.5.13.0207, SQLite3, Git 1.9.0, Ubuntu 12.04. Error log: @@ -38,11 +38,11 @@ Error log: ### Feature Request -There is no standard form of making a feature request, just try to describe the feature as clear as possible because team members may not have experience with the functionality you're talking about. +There is no standard form of making a feature request. Just try to describe the feature as clearly as possible, because team members may not have experience with the functionality you're talking about. ### Pull Request -Pull requests are always welcome, but note that **ALL PULL REQUESTS MUST SEND TO `DEV` BRANCH**. +Pull requests are always welcome, but note that **ALL PULL REQUESTS MUST APPLY TO THE `DEV` 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. @@ -52,7 +52,7 @@ We're trying very hard to keep Gogs lean and focused. We don't want it to do eve ### Ask For Help -Before open any new issue, please check your problem on [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.md) and [FAQs](http://gogs.io/docs/intro/faqs.html) pages. +Before opening an issue, please make sure your problem isn't already addressed on the [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.md) and [FAQs](http://gogs.io/docs/intro/faqs.html) pages. ## Things To Notice @@ -3,7 +3,7 @@ Gogs - Go Git Service [](https://gitter.im/gogits/gogs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -Gogs(Go Git Service) is a painless self-hosted Git Service written in Go. +Gogs (Go Git Service) is a painless self-hosted Git service written in Go.  @@ -12,9 +12,9 @@ Gogs(Go Git Service) is a painless self-hosted Git Service written in Go. ### NOTICES - Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) has been reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site. -- Demo site [try.gogs.io](https://try.gogs.io) is running under `dev` branch. +- The demo site [try.gogs.io](https://try.gogs.io) is running under `dev` branch. - You **MUST** read [CONTRIBUTING.md](CONTRIBUTING.md) before you start filing a issue or making a Pull Request. -- If you think there are vulnerabilities in the project, please talk private to **u@gogs.io**, thanks! +- If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**. Thanks! #### Other language version @@ -22,15 +22,15 @@ Gogs(Go Git Service) is a painless self-hosted Git Service written in Go. ## Purpose -The goal of this project is to make the easiest, fastest and most painless way to set up a self-hosted Git service. With Go, this can be done in independent binary distribution across **ALL platforms** that Go supports, including Linux, Mac OS X, and Windows. +The goal of this project is to make the easiest, fastest, and most painless way to set up a self-hosted Git service. With Go, this can be done via an independent binary distribution across **ALL platforms** that Go supports, including Linux, Mac OS X, and Windows. ## Overview -- Please see [Documentation](http://gogs.io/docs/intro/) for project design, known issues, and change log. -- See [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team. -- Try it before anything? Do it [online](https://try.gogs.io/Unknown/gogs) or go down to **Installation -> Install from binary** section! -- Having troubles? Get help from [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.md). -- Want to help on localization? Check out [Crowdin](https://crowdin.com/project/gogs)! +- Please see the [Documentation](http://gogs.io/docs/intro/) for project design, known issues, and change log. +- See the [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team. +- Want to try it before doing anything else? Do it [online](https://try.gogs.io/unknwon/gogs) or go down to the **Installation -> Install from binary** section! +- Having trouble? Get help with [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.md). +- Want to help with localization? Check out [Crowdin](https://crowdin.com/project/gogs)! ## Features @@ -46,22 +46,22 @@ The goal of this project is to make the easiest, fastest and most painless way t - Repository Git hooks - Add/remove repository collaborators - Gravatar and cache support -- Mail service(register, issue) +- Mail service (register, issue) - Administration panel - Slack webhook integration - Drone CI integration - Supports MySQL, PostgreSQL and SQLite3 -- Social account login(GitHub, Google, QQ, Weibo) -- Multi-language support([9 languages](https://crowdin.com/project/gogs)) +- Social account login (GitHub, Google, QQ, Weibo) +- Multi-language support ([10 languages](https://crowdin.com/project/gogs)) ## System Requirements -- A cheap Raspberry Pi is powerful enough to match the minimal requirement. -- 4 CPU Cores and 1GB RAM would be the baseline for teamwork. +- A cheap Raspberry Pi is powerful enough for basic functionality. +- At least 4 CPU cores and 1GB RAM would be the baseline for teamwork. ## Installation -Make sure you install [Prerequirements](http://gogs.io/docs/installation/) first. +Make sure you install the [prerequisites](http://gogs.io/docs/installation/) first. There are 5 ways to install Gogs: diff --git a/README_ZH.md b/README_ZH.md index 54e66315..b6d74e7b 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -1,4 +1,4 @@ -Gogs - Go Git Service [](https://app.wercker.com/project/bykey/ad0bdb0bc450ac6f09bc56b9640a50aa) [](https://travis-ci.org/gogits/gogs) +Gogs - Go Git Service [](https://travis-ci.org/gogits/gogs) ===================== Gogs(Go Git Service) 是一个基于 Go 语言的自助 Git 服务。 @@ -15,7 +15,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自 - 有关项目设计、已知问题和变更日志,请通过 [使用手册](http://gogs.io/docs/intro/) 查看。 - 您可以到 [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) 跟随开发团队的脚步。 -- 想要先睹为快?通过 [在线体验](https://try.gogs.io/Unknown/gogs) 或查看 **安装部署 -> 二进制安装** 小节。 +- 想要先睹为快?通过 [在线体验](https://try.gogs.io/unknwon/gogs) 或查看 **安装部署 -> 二进制安装** 小节。 - 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.md) 页面获取帮助。 - 希望帮助多国语言界面的翻译吗?请立即访问 [Crowdin](https://crowdin.com/project/gogs)! @@ -39,7 +39,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自 - Drone CI 持续部署集成 - 支持 MySQL、PostgreSQL 以及 SQLite3 数据库 - 社交帐号登录(GitHub、Google、QQ、微博) -- 多语言支持([9 种语言]([more](https://crowdin.com/project/gogs))) +- 多语言支持([10 种语言]([more](https://crowdin.com/project/gogs))) ## 系统要求 diff --git a/cmd/cert_stub.go b/cmd/cert_stub.go index 69c9821e..1b68ca83 100644 --- a/cmd/cert_stub.go +++ b/cmd/cert_stub.go @@ -9,7 +9,6 @@ package cmd import ( "fmt" "os" - "time" "github.com/codegangsta/cli" ) @@ -20,14 +19,6 @@ var CmdCert = cli.Command{ 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, - Flags: []cli.Flag{ - cli.StringFlag{"host", "", "Comma-separated hostnames and IPs to generate a certificate for", ""}, - cli.StringFlag{"ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521", ""}, - cli.IntFlag{"rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set", ""}, - cli.StringFlag{"start-date", "", "Creation date formatted as Jan 1 15:04:05 2011", ""}, - cli.DurationFlag{"duration", 365 * 24 * time.Hour, "Duration that certificate is valid for", ""}, - cli.BoolFlag{"ca", "whether this cert should be its own Certificate Authority", ""}, - }, } func runCert(ctx *cli.Context) { diff --git a/cmd/dump.go b/cmd/dump.go index 3e1ccdb8..36bb4f03 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -25,11 +25,15 @@ var CmdDump = cli.Command{ It can be used for backup and capture Gogs server image to send to maintainer`, Action: runDump, Flags: []cli.Flag{ + cli.StringFlag{"config, c", "custom/conf/app.ini", "Custom configuration file path", ""}, cli.BoolFlag{"verbose, v", "show process details", ""}, }, } func runDump(ctx *cli.Context) { + if ctx.IsSet("config") { + setting.CustomConf = ctx.String("config") + } setting.NewConfigContext() models.LoadModelsConfig() models.SetEngine() diff --git a/cmd/fix.go b/cmd/fix.go deleted file mode 100644 index eff85d62..00000000 --- a/cmd/fix.go +++ /dev/null @@ -1,184 +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 cmd - -import ( - "bufio" - "fmt" - "io" - "io/ioutil" - "os" - "path" - "runtime" - "strings" - - "github.com/Unknwon/com" - "github.com/codegangsta/cli" - - "github.com/gogits/gogs/models" - "github.com/gogits/gogs/modules/setting" -) - -var CmdFix = cli.Command{ - Name: "fix", - Usage: "This command for upgrade from old version", - Action: runFix, - Subcommands: fixCommands, - Flags: []cli.Flag{}, -} - -func runFix(ctx *cli.Context) { -} - -var fixCommands = []cli.Command{ - { - Name: "location", - Usage: "Change Gogs app location", - Description: `Command location fixes location change of Gogs - -gogs fix location <old Gogs path> -`, - Action: runFixLocation, - }, -} - -// rewriteAuthorizedKeys replaces old Gogs path to the new one. -func rewriteAuthorizedKeys(sshPath, oldPath, newPath string) error { - fr, err := os.Open(sshPath) - if err != nil { - return err - } - defer fr.Close() - - tmpPath := sshPath + ".tmp" - fw, err := os.Create(tmpPath) - if err != nil { - return err - } - defer fw.Close() - - oldPath = "command=\"" + oldPath + " serv" - newPath = "command=\"" + newPath + " serv" - buf := bufio.NewReader(fr) - for { - line, errRead := buf.ReadString('\n') - line = strings.TrimSpace(line) - - if errRead != nil { - if errRead != io.EOF { - return errRead - } - - // Reached end of file, if nothing to read then break, - // otherwise handle the last line. - if len(line) == 0 { - break - } - } - - // Still finding the line, copy the line that currently read. - if _, err = fw.WriteString(strings.Replace(line, oldPath, newPath, 1) + "\n"); err != nil { - return err - } - - if errRead == io.EOF { - break - } - } - - if err = os.Remove(sshPath); err != nil { - return err - } - return os.Rename(tmpPath, sshPath) -} - -func rewriteUpdateHook(path, appPath string) error { - if runtime.GOOS == "windows" { - rp := strings.NewReplacer("\\", "/") - appPath = "\"" + rp.Replace(appPath) + "\"" - } else { - rp := strings.NewReplacer("\\", "/", " ", "\\ ") - appPath = rp.Replace(appPath) - } - - if err := ioutil.WriteFile(path, []byte(fmt.Sprintf(models.TPL_UPDATE_HOOK, - setting.ScriptType, appPath)), os.ModePerm); err != nil { - return err - } - return nil -} - -func walkDir(rootPath, recPath, appPath string, depth int) error { - depth++ - if depth > 3 { - return nil - } else if depth == 3 { - if err := rewriteUpdateHook(path.Join(rootPath, "hooks/update"), appPath); err != nil { - return err - } - } - - dir, err := os.Open(rootPath) - if err != nil { - return err - } - defer dir.Close() - - fis, err := dir.Readdir(0) - if err != nil { - return err - } - - for _, fi := range fis { - if strings.Contains(fi.Name(), ".DS_Store") { - continue - } - - relPath := path.Join(recPath, fi.Name()) - curPath := path.Join(rootPath, fi.Name()) - if fi.IsDir() { - if err = walkDir(curPath, relPath, appPath, depth); err != nil { - return err - } - } - } - return nil -} - -func runFixLocation(ctx *cli.Context) { - if len(ctx.Args()) != 1 { - fmt.Println("Incorrect arguments number, expect 1") - os.Exit(2) - } - - execPath, _ := setting.ExecPath() - - oldPath := ctx.Args().First() - fmt.Printf("Old location: %s\n", oldPath) - fmt.Println("This command should be executed in the new Gogs path") - fmt.Printf("Do you want to change Gogs app path from old location to:\n") - fmt.Printf("-> %s?\n", execPath) - fmt.Print("Press <enter> to continue, use <Ctrl+c> to exit.") - fmt.Scanln() - - // Fix in authorized_keys file. - sshPath := path.Join(models.SSHPath, "authorized_keys") - if com.IsFile(sshPath) { - fmt.Printf("Fixing pathes in file: %s\n", sshPath) - if err := rewriteAuthorizedKeys(sshPath, oldPath, execPath); err != nil { - fmt.Println(err) - os.Exit(1) - } - } - - // Fix position in gogs-repositories. - setting.NewConfigContext() - fmt.Printf("Fixing pathes in repositories: %s\n", setting.RepoRootPath) - if err := walkDir(setting.RepoRootPath, "", execPath, 0); err != nil { - fmt.Println(err) - os.Exit(1) - } - fmt.Println("Fix position finished!") -} diff --git a/cmd/serve.go b/cmd/serve.go index 1f5d944d..25f7dd91 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -27,7 +27,9 @@ var CmdServ = cli.Command{ Usage: "This command should only be called by SSH shell", Description: `Serv provide access auth for repositories`, Action: runServ, - Flags: []cli.Flag{}, + Flags: []cli.Flag{ + cli.StringFlag{"config, c", "custom/conf/app.ini", "Custom configuration file path", ""}, + }, } func setup(logPath string) { @@ -83,9 +85,15 @@ func In(b string, sl map[string]models.AccessType) bool { } func runServ(k *cli.Context) { + if k.IsSet("config") { + setting.CustomConf = k.String("config") + } setup("serv.log") - keys := strings.Split(os.Args[2], "-") + if len(k.Args()) < 1 { + log.GitLogger.Fatal(2, "Not enough arguments") + } + keys := strings.Split(k.Args()[0], "-") if len(keys) != 2 { println("Gogs: auth file format error") log.GitLogger.Fatal(2, "Invalid auth file format: %s", os.Args[2]) diff --git a/cmd/update.go b/cmd/update.go index cc55693e..c9eaeccf 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -11,6 +11,7 @@ import ( "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/log" + "github.com/gogits/gogs/modules/setting" ) var CmdUpdate = cli.Command{ @@ -18,10 +19,15 @@ var CmdUpdate = cli.Command{ Usage: "This command should only be called by SSH shell", Description: `Update get pushed info and insert into database`, Action: runUpdate, - Flags: []cli.Flag{}, + Flags: []cli.Flag{ + cli.StringFlag{"config, c", "custom/conf/app.ini", "Custom configuration file path", ""}, + }, } func runUpdate(c *cli.Context) { + if c.IsSet("config") { + setting.CustomConf = c.String("config") + } cmd := os.Getenv("SSH_ORIGINAL_COMMAND") if cmd == "" { return @@ -55,6 +55,7 @@ and it takes care of all the other things for you`, Action: runWeb, Flags: []cli.Flag{ cli.StringFlag{"port, p", "3000", "Temporary port number to prevent conflict", ""}, + cli.StringFlag{"config, c", "custom/conf/app.ini", "Custom configuration file path", ""}, }, } @@ -78,7 +79,7 @@ func checkVersion() { // Check dependency version. checkers := []VerChecker{ {"github.com/Unknwon/macaron", macaron.Version, "0.5.1"}, - {"github.com/macaron-contrib/binding", binding.Version, "0.0.4"}, + {"github.com/macaron-contrib/binding", binding.Version, "0.0.5"}, {"github.com/macaron-contrib/cache", cache.Version, "0.0.7"}, {"github.com/macaron-contrib/csrf", csrf.Version, "0.0.3"}, {"github.com/macaron-contrib/i18n", i18n.Version, "0.0.5"}, @@ -165,6 +166,9 @@ func newMacaron() *macaron.Macaron { } func runWeb(ctx *cli.Context) { + if ctx.IsSet("config") { + setting.CustomConf = ctx.String("config") + } routers.GlobalInit() checkVersion() @@ -225,7 +229,7 @@ func runWeb(ctx *cli.Context) { }) m.Any("/*", func(ctx *middleware.Context) { - ctx.JSON(404, &base.ApiJsonErr{"Not Found", base.DOC_URL}) + ctx.HandleAPI(404, "Page not found") }) }) }) diff --git a/conf/app.ini b/conf/app.ini index 17d1a3b3..2019557b 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -89,6 +89,8 @@ ENABLE_REVERSE_PROXY_AUTO_REGISTERATION = false TASK_INTERVAL = 1 ; Deliver timeout in seconds DELIVER_TIMEOUT = 5 +; Allow insecure certification +SKIP_TLS_VERIFY = false [mailer] ENABLED = false @@ -280,5 +282,5 @@ INTERVAL = 24 ARGS = [i18n] -LANGS = en-US,zh-CN,zh-HK,de-DE,fr-CA,nl-NL,lv-LV,ru-RU,ja-JP -NAMES = English,简体中文,繁體中文,Deutsch,Français,Nederlands,Latviešu,Русский,日本语 +LANGS = en-US,zh-CN,zh-HK,de-DE,fr-CA,nl-NL,lv-LV,ru-RU,ja-JP,es-ES +NAMES = English,简体中文,繁體中文,Deutsch,Français,Nederlands,Latviešu,Русский,日本语,Español diff --git a/conf/locale/locale_de-DE.ini b/conf/locale/locale_de-DE.ini index 2d22d049..31ee931b 100755 --- a/conf/locale/locale_de-DE.ini +++ b/conf/locale/locale_de-DE.ini @@ -59,6 +59,8 @@ run_user=Ausführender Benutzer run_user_helper=Der Benutzer muss die Zugriffsberechtigung für das Repository Root-Verzeichnis haben und der ausführende Benutzer von Gogs sein.
domain=Domain
domain_helper=Dies hat Auswirkung auf die SSH clone URLs.
+http_port=HTTP Port
+http_port_helper=Port number which application will listen on.
app_url=Anwendungs-URL
app_url_helper=Dies hat Auswirkung auf die HTTP/HTTPS clone URLs und für die E-Mails.
email_title=E-Mail-Service Einstellungen (optional)
@@ -512,6 +514,11 @@ dashboard.delete_repo_archives=Alle Repository-Archive löschen dashboard.delete_repo_archives_success=Alle Repositoriy-Archive wurden gelöscht.
dashboard.git_gc_repos=Führe Garbage Collection auf Repositories aus
dashboard.git_gc_repos_success=Garbage Collection wurde auf allen Repositories erfolgreich ausgeführt.
+dashboard.resync_all_sshkeys=Rewrite '.ssh/autorized_key' file (caution: non-Gogs keys will be lost)
+dashboard.resync_all_sshkeys_success=All public keys have been rewritten successfully.
+dashboard.resync_all_update_hooks=Rewrite all update hook of repositories (needed when custom config path is changed)
+dashboard.resync_all_update_hooks_success=All repositories' update hook have been rewritten successfully.
+
dashboard.server_uptime=Server-Uptime
dashboard.current_goroutine=Aktuelle Goroutines
dashboard.current_memory_usage=Aktuelle Speichernutzung
@@ -631,7 +638,7 @@ config.db_path_helper=(nur für "sqlite3") config.service_config=Service-Einstellungen
config.register_email_confirm=E-Mail-Bestätigung bei Registrierung
config.disable_register=Registrierung deaktivieren
-config.show_registration_button = Registrierungs-Button anzeigen
+config.show_registration_button=Show Register Button
config.require_sign_in_view=Ansehen erfordert Registrierung
config.mail_notify=E-Mail-Benachrichtigung
config.enable_cache_avatar=Avatar-Cache aktivieren
@@ -640,6 +647,7 @@ config.reset_password_code_lives=Passwortcode Lebensdauer config.webhook_config=Webhook-Einstellungen
config.task_interval=Task-Intervall
config.deliver_timeout=Zeitlimit für Zustellung
+config.skip_tls_verify=Skip TLS Verify
config.mailer_config=Mailer-Einstellungen
config.mailer_enabled=Aktiviert
config.mailer_name=Name
@@ -687,8 +695,8 @@ notices.delete_success=System-Mitteilung erfolgreich gelöscht. [action]
create_repo=hat Repository <a href="%s/%s">%s</a> erstellt
commit_repo=hat nach <a href="%s/%s/src/%s">%s</a> in <a href="%s/%s">%s</a> gepusht
-create_issue=hat Issue <a href="%s/%s/issues/%s">%s#%s</a> eröffnet
-comment_issue=hat Issue <a href="%s/%s/issues/%s">%s#%s</a> kommentiert
+create_issue=`hat Issue <a href="%s/issues/%s">%[1]s#%[2]s</a> eröffnet`
+comment_issue=`hat Issue <a href="%s/issues/%s">%[1]s#%[2]s</a> kommentiert`
transfer_repo=hat Repository <code>%s</code> transferiert an <a href="/%s%s">%s</a>
push_tag=hat nach <a href="%s/%s/src/%s">%s</a> in <a href="%s/%s">%s</a> gepusht
compare_2_commits=Zeige Vergleich dieser 2 Commits
@@ -714,16 +722,3 @@ years=%[2]s %[1]d Jahren raw_seconds=Sekunden
raw_minutes=Minuten
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/conf/locale/locale_en-US.ini b/conf/locale/locale_en-US.ini index 2e83025e..f05287f5 100644 --- a/conf/locale/locale_en-US.ini +++ b/conf/locale/locale_en-US.ini @@ -67,7 +67,7 @@ email_title = E-mail Service Settings (Optional) smtp_host = SMTP Host mailer_user = Sender E-mail mailer_password = Sender Password -notify_title = Notification Settings(Optional) +notify_title = Notification Settings (Optional) register_confirm = Enable Register Confirmation mail_notify = Enable Mail Notification admin_title = Admin Account Settings @@ -280,14 +280,14 @@ license_helper = Select a license file init_readme = Initialize this repository with a README.md create_repo = Create Repository default_branch = Default Branch -mirror_interval = Mirror Interval(hour) -goget_meta = Go-Get Meta -goget_meta_helper = This repository will be <span class="label label-blue label-radius">Go-Getable</span> +mirror_interval = Mirror Interval (hour) need_auth = Need Authorization migrate_type = Migration Type migrate_type_helper = This repository will be a <span class="label label-blue label-radius">Mirror</span> migrate_repo = Migrate Repository +migrate.clone_address = Clone Address +migrate.invalid_local_path = Invalid local path, it does not exist or not a directory. copy_link = Copy click_to_copy = Copy to clipboard @@ -514,8 +514,11 @@ dashboard.delete_repo_archives = Delete all repositories archives dashboard.delete_repo_archives_success = All repositories archives have been deleted successfully. dashboard.git_gc_repos = Do garbage collection on repositories dashboard.git_gc_repos_success = All repositories have done garbage collection successfully. -dashboard.resync_all_sshkeys = Rewrite '.ssh/autorized_key' file(caution: non-Gogs keys will be lost) +dashboard.resync_all_sshkeys = Rewrite '.ssh/autorized_key' file (caution: non-Gogs keys will be lost) dashboard.resync_all_sshkeys_success = All public keys have been rewritten successfully. +dashboard.resync_all_update_hooks = Rewrite all update hook of repositories (needed when custom config path is changed) +dashboard.resync_all_update_hooks_success = All repositories' update hook have been rewritten successfully. + dashboard.server_uptime = Server Uptime dashboard.current_goroutine = Current Goroutines dashboard.current_memory_usage = Current Memory Usage @@ -647,6 +650,7 @@ config.reset_password_code_lives = Reset Password Code Lives config.webhook_config = Webhook Configuration config.task_interval = Task Interval config.deliver_timeout = Deliver Timeout +config.skip_tls_verify = Skip TLS Verify config.mailer_config = Mailer Configuration config.mailer_enabled = Enabled config.mailer_name = Name @@ -694,8 +698,8 @@ notices.delete_success = System notice has been deleted successfully. [action] create_repo = created repository <a href="%s/%s">%s</a> commit_repo = pushed to <a href="%s/%s/src/%s">%s</a> at <a href="%s/%s">%s</a> -create_issue = opened issue <a href="%s/%s/issues/%s">%s#%s</a> -comment_issue = commented on issue <a href="%s/%s/issues/%s">%s#%s</a> +create_issue = `opened issue <a href="%s/issues/%s">%[1]s#%[2]s</a>` +comment_issue = `commented on issue <a href="%s/issues/%s">%[1]s#%[2]s</a>` transfer_repo = transfered repository <code>%s</code> to <a href="/%s%s">%s</a> push_tag = pushed tag <a href="%s/%s/src/%s">%s</a> to <a href="%s/%s">%s</a> compare_2_commits = View comparison for these 2 commits diff --git a/conf/locale/locale_es-ES.ini b/conf/locale/locale_es-ES.ini new file mode 100755 index 00000000..046bab89 --- /dev/null +++ b/conf/locale/locale_es-ES.ini @@ -0,0 +1,724 @@ +app_desc=Un servicio de Git auto alojado y sin complicaciones
+
+home=Incio
+dashboard=Panel de control
+explore=Explorar
+help=Ayuda
+sign_in=Iniciar sesión
+social_sign_in=Inicio de sesión social: 2° paso <small>cuenta de asociado</small>
+sign_out=Cerrar sesión
+sign_up=Suscripción
+register=Registro
+website=Pagina Web
+version=Versión
+page=Página
+template=Plantilla
+language=Lenguaje
+
+username=Nombre de usuario
+email=Correo electrónico
+password=Contraseña
+re_type=Ingrese de nuevo
+captcha=Captcha
+
+repository=Repositorio
+organization=Organización
+mirror=Espejo
+new_repo=Nuevo repositorio
+new_migrate=Nueva Migración
+new_fork=Nuevo Fork del Repositorio
+new_org=Nueva organización
+manage_org=Administrar organizaciones
+admin_panel=Panel de administración
+account_settings=Configuraciones de la cuenta
+settings=Configuraciones
+
+news_feed=entrada de noticias
+pull_requests=Solicitudes de retiro
+issues=Publicaciones
+
+cancel=Cancelar
+
+[install]
+install=Instalación
+title=Pasos de la instalación por primera vez
+requite_db_desc=Gogs necesita MySQL, PostgreSQL o SQLite3.
+db_type=Tipo de base de datos
+host=Anfitrión
+user=Usuario
+password=Contraseña
+db_name=Nombre de la base de datos
+db_helper=Por favor utilice el motor INNODB con la configuración de caracteres utf8_general_ci para MySQL.
+ssl_mode=Modo SSL
+path=Ruta
+sqlite_helper=Ruta del archivo de la base de datos de SQLite3.
+general_title=Configuraciones Generales de Gogs
+repo_path=Ruta del repositorio de Raiz (Root)
+repo_path_helper=Todos los repositorios remotos de Git se guardarán en este directorio.
+run_user=Abrir el usuario
+run_user_helper=El usuario necesita tener acceso a la Ruta Raíz del Repositorio y ejecutar Gogs.
+domain=Dominio
+domain_helper=Esto afecta a las URLs para clonar por SSH.
+http_port=Puerto HTTP
+http_port_helper=Puerto en el que escuchará la aplicación.
+app_url=URL de la aplicación
+app_url_helper=Esto afecta a las URLs para clonar por HTTP/HTTPS y a algunos correos electrónicos.
+email_title=Configuración del Servicio de Correo (Opcional)
+smtp_host=SMTP Host
+mailer_user=Remitente del Correo Electrónico
+mailer_password=Contraseña del Remitente
+notify_title=Configuración de Notificaciones (Opcional)
+register_confirm=Habilitar la Confirmación en el Registro
+mail_notify=Habilitar las Notificaciones de Correo
+admin_title=Configuración de la Cuenta de Administrador
+admin_name=Nombre de usuario
+admin_password=Contraseña
+confirm_password=Confirmar Contraseña
+admin_email=Correo electrónico
+install_gogs=Instalar Gogs
+test_git_failed=Fallo al probar el comando 'git': %v
+sqlite3_not_available=Tu versión no soporta SQLite3, por favor descarga el binario oficial desde %s, NO la versión de gobuild.
+invalid_db_setting=La configuración de la base de datos no es correcta: %v
+invalid_repo_path=La ruta de la raíz del repositorio es inválida: %v
+run_user_not_match=El usuario que está ejecutando la aplicación no es el usuario actual: %s -> %s
+save_config_failed=Error al guardar la configuración: %v
+invalid_admin_setting=La configuración de la cuenta de administración es inválida: %v
+install_success=Bienvenido! Estamos encantados de que hayas escogido Gogs, diviértete y cuídate.
+
+[home]
+uname_holder=Nombre de usuario o correo electrónico
+password_holder=Contraseña
+switch_dashboard_context=Cambiar el contexto del Dashboard
+my_repos=Mis Repositorios
+collaborative_repos=Repositorios Colaborativos
+my_orgs=Mis Organizaciones
+my_mirrors=Mis Mirrors
+
+[explore]
+repos=Repositorios
+
+[auth]
+create_new_account=Crear una Nueva Cuenta
+register_hepler_msg=¿Ya tienes una cuenta? ¡Inicia sesión!
+social_register_hepler_msg=¿Ya tienes una cuenta? ¡Enlázala!
+disable_register_prompt=Lo sentimos, el registro está deshabilitado. Por favor, contacta con el administrador del sitio.
+disable_register_mail=Lo sentimos. Los correos de Confirmación de Registro están deshabilitados.
+remember_me=Recuérdame
+forgot_password=He olvidado mi contraseña
+forget_password=¿Has olvidado tu contraseña?
+sign_up_now=¿Necesitas una cuenta? Regístrate ahora.
+confirmation_mail_sent_prompt=Un nuevo correo de confirmación se ha enviado a <b>%s</b>. Por favor, comprueba tu bandeja de entrada en las siguientes %d horas para completar el proceso de registro.
+sign_in_email=Inicia sesión con tu correo electrónico
+active_your_account=Activa tu cuenta
+resent_limit_prompt=Lo sentimos, estás solicitando el reenvío del mail de activación con demasiada frecuencia. Por favor, espera 3 minutos.
+has_unconfirmed_mail=Hola %s, tu correo electrónico (<b>%s</b>) no está confirmado. Si no has recibido un correo de confirmación o necesitas que lo enviemos de nuevo, por favor, haz click en el siguiente botón.
+resend_mail=Haz click aquí para reenviar tu correo electrónico de activación
+email_not_associate=Esta dirección de correo electrónico no esta asociada a cuenta alguna.
+send_reset_mail=Haga clic aquí para (re)enviar el correo para el restablecimiento de la contraseña
+reset_password=Restablecer su contraseña
+invalid_code=Lo sentimos, su código de confirmación ha expirado o no es valido.
+reset_password_helper=Haga Clic aquí para restablecer su contraseña
+password_too_short=La longitud de la contraseña no puede ser menor a 6.
+
+[form]
+UserName=Nombre de usuario
+RepoName=Nombre del repositorio
+Email=Dirección de correo electrónico
+Password=Contraseña
+Retype=Vuelva a escribir la contraseña
+SSHTitle=Nombre de la Clave de SSH
+HttpsUrl=HTTPS URL
+PayloadUrl=URL de carga
+TeamName=Nombre del equipo
+AuthName=Nombre de autorización
+AdminEmail=Correo electrónico del administrador
+
+require_error=` no puede estar vacío.`
+alpha_dash_error=` los caracteres deben ser Alfanumericos o dash(-_).`
+alpha_dash_dot_error=` debe ser un caracter alfanumérivo válido, un guión alto o bajo (-_) o un signo de puntuación.`
+min_size_error=` debe contener al menos %s caracteres.`
+max_size_error=` debe contener como máximo %s caracteres.`
+email_error=` no es una dirección de correo válida.`
+url_error=` no es una URL válida.`
+unknown_error=Error desconocido:
+captcha_incorrect=El captcha no es válido.
+password_not_match=La contraseña de confirmación no coincide.
+
+username_been_taken=Ya existe un usuario con este nombre.
+repo_name_been_taken=Ya existe un repositorio con este nombre.
+org_name_been_taken=Ya existe una organización con este nombre.
+team_name_been_taken=Ya existe un equipo con este nombre.
+email_been_used=Esta dirección de correo electrónico ya está en uso.
+ssh_key_been_used=Este nombre de clave pública ya está en uso.
+illegal_username=Tu nombre de usuario contiene caracteres inválidos.
+illegal_repo_name=El nombre del repositorio contiene caracteres inválidos.
+illegal_org_name=El nombre de la organización contiene caracteres inválidos.
+illegal_team_name=El nombre del equipo contiene caracteres inválidos.
+username_password_incorrect=Nombre de usuario o contraseña incorrectos.
+enterred_invalid_repo_name=Por favor, asegúrate de que has introducido correctamente el nombre del repositorio.
+enterred_invalid_owner_name=Por favor, asegúrate de que has introducido correctamente el nombre del propietario.
+enterred_invalid_password=Por favor, asegúrate de que has introducido correctamente tu contraseña.
+user_not_exist=El usuario indicado no existe.
+last_org_owner=El usuario que se intenta eliminar es el último miembro del equipo de propietarios. Debe existir otro propietario.
+
+invalid_ssh_key=Lo sentimos, no somos capaces de verificar tu clave SSH: %s
+unable_verify_ssh_key=Gogs no puede velificar tu clave SSH, pero asumimos que es válida. Por favor, asegúrate de que es así.
+auth_failed=Error de autenticación: %v
+
+still_own_repo=Tu cuenta es la propietaria de uno o más repositorios, tienes que borrarlos o transferirlos primero.
+still_has_org=Tu cuenta es miembro de una o más organizaciones, tienes que abandonarlas o eliminarlas primero.
+org_still_own_repo=Esta organización es dueña de uno o más repositorios, tienes que eliminarlos o transferirlos primero.
+
+still_own_user=Esta autenticación está en uso por algunos usuarios, debes moverlos y antes de eliminarla.
+
+target_branch_not_exist=La rama de destino no existe
+
+[user]
+change_avatar=Cambia tu avatar en gravatar.com
+change_custom_avatar=Cambia tu avatar en la configuración
+join_on=Registrado en
+repositories=Repositorios
+activity=Actividad pública
+followers=Seguidores
+starred=Destacados
+following=Siguiendo
+
+[settings]
+profile=Perfil
+password=Contraseña
+ssh_keys=Claves SSH
+social=Redes Sociales
+applications=Aplicaciones
+orgs=Organizaciones
+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.
+full_name=Nombre Completo
+website=Página Web
+location=Localización
+update_profile=Actualizar Perfil
+update_profile_success=Tu perfil se ha actualizado correctamente.
+change_username=Nombre de usuario modificado
+change_username_desc=El nombre de usuario ha sido modificado, ¿quieres continuar? Esta acción afectará a todos los enlaces relacionados con tu cuenta.
+continue=Continuar
+cancel=Cancelar
+
+enable_custom_avatar=Activar Avatar Personalizado
+enable_custom_avatar_helper=Activa esto para desactivar los avatares de Gravatar
+choose_new_avatar=Selecciona nuevo avatar
+update_avatar=Actualizar Configuración del Avatar
+uploaded_avatar_not_a_image=El archivo enviado no es una imagen.
+no_custom_avatar_available=No hay ningún avatar personalizado disponible, no se puede habilitar.
+update_avatar_success=La configuración de tu avatar se ha actualizado correctamente.
+
+change_password=Cambiar contraseña
+old_password=Contraseña actual
+new_password=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.
+
+emails=Direcciones de correo electrónico
+manage_emails=Gestionar direcciones de correo electrónico
+email_desc=Tu dirección de correo principal se utilizará para las notificaciones y otras operaciones.
+primary=Principal
+primary_email=Marcar como principal
+delete_email=Eliminar
+add_new_email=Añadir nueva dirección de correo electrónico
+add_email=Añadir correo electrónico
+add_email_success=Tu nuevo correo electrónico se ha añadido correctamente.
+
+manage_ssh_keys=Gestionar Claves SSH
+add_key=Añadir Clave
+ssh_desc=Esta es la lista de claves SSH asociadas con tu cuenta. Elimina cualquier clave que no reconozcas.
+ssh_helper=<strong>¿Necesitas ayuda?</strong>. Consulta nuestra guía para <a href="%s">generar claves SSH</a> o solucionar <a href="%s">problemas comunes de SSH</a>.
+add_new_key=Añadir clave SSH
+key_name=Nombre de la Clave
+key_content=Contenido
+add_key_success=¡Se ha añadido una nueva clave SSH!
+delete_key=Eliminar
+add_on=Añadido en
+last_used=Utilizado por última vez en
+no_activity=No hay actividad reciente
+
+manage_social=Gestionar Redes Sociales asociadas
+social_desc=Esta es una lista de las Redes Sociales asociadas. Elimina cualquier vínculo que no reconozcas.
+unbind=Desvincular
+unbind_success=La Red Social ha sido desvinculada.
+
+manage_access_token=Gestionar los Tokens de Acceso personales
+generate_new_token=Generar nuevo Token
+tokens_desc=Tokens generados que pueden ser usados para acceder al API de Gogs.
+new_token_desc=Desde ahora, todos los tokens tendrán acceso completo a tu cuenta.
+token_name=Nombre del Token
+generate_token=Generar Token
+generate_token_succees=¡Los nuevos tokens de acceso se han generado correctamente! Asegúrate de copiar tu nuevo token de acceso personal. ¡No podrás verlo de nuevo!
+delete_token=Eliminar
+delete_token_success=¡Los tokens de acceso personales se han eliminado correctamente! No olvides actualizar las aplicaciones que los usasen.
+
+delete_account=Elimina tu cuenta
+delete_prompt=La operación eliminará tu cuenta de forma permanente y ¡<strong>NO</strong> se puede deshacer!
+confirm_delete_account=Confirmar Eliminación
+delete_account_title=Eliminación de Cuenta
+delete_account_desc=Esta cuenta se va a eliminar permanentemente, ¿quieres continuar?
+
+[repo]
+owner=Propietario
+repo_name=Nombre del Repositorio
+repo_name_helper=Los grandes nombres de repositorios son cortos, memorables y <strong>únicos</strong>.
+visibility=Visibilidad
+visiblity_helper=Este repositorio es <span class="label label-red label-radius">Privado</span>
+fork_repo=Hacer Fork del repositorio
+fork_from=Crear un Fork desde
+fork_visiblity_helper=No es posible cambiar la visibilidad de un Fork
+repo_desc=Descripción
+repo_lang=Idioma
+repo_lang_helper=Selecciona un fichero .gitignore
+license=Licencia
+license_helper=Selecciona un fichero de licencia
+init_readme=Crear este repositorio con un fichero README.md
+create_repo=Crear Repositorio
+default_branch=Rama por defecto
+mirror_interval=Intervalo de mirror(en horas)
+goget_meta=Go-Get Meta
+goget_meta_helper=Este repositorio será <span class="label label-blue label-radius">Go-Getable</span>
+
+need_auth=Requiere Autorización
+migrate_type=Tipo de Migración
+migrate_type_helper=Este repositorio será un <span class="label label-blue label-radius">Mirror</span>
+migrate_repo=Migrar Repositorio
+
+copy_link=Copiar
+click_to_copy=Copiar al portapapeles
+copied=Copiado correctamente
+clone_helper=¿Necesitas ayuda con el clone? ¡Consulta la <a target="_blank" href="%s">Ayuda</a>!
+unwatch=Dejar de vigilar
+watch=Vigilar
+unstar=Eliminar destacado
+star=Destacar
+fork=Fork
+
+no_desc=Sin Descripción
+quick_guide=Guía Rápida
+clone_this_repo=Clonar este repositorio
+create_new_repo_command=Crear un nuevo repositorio desde línea de comandos
+push_exist_repo=Hacer Push de un repositorio existente desde línea de comandos
+
+branch=Rama
+tree=Árbol
+branch_and_tags=Ramas y Etiquetas
+branches=Ramas
+tags=Etiquetas
+issues=Incidencias
+commits=Commits
+releases=Releases
+file_raw=Raw
+file_history=Histórico
+file_view_raw=Ver Raw
+
+commits.commits=Commits
+commits.search=Buscar Commits
+commits.find=Buscar
+commits.author=Autor
+commits.message=Mensaje
+commits.date=Fecha
+commits.older=Anterior
+commits.newer=Posterior
+
+settings=Configuración
+settings.options=Opciones
+settings.collaboration=Colaboración
+settings.hooks=Webhooks
+settings.githooks=Git Hooks
+settings.deploy_keys=Claves de Despliegue
+settings.basic_settings=Configuración Básica
+settings.danger_zone=Zona de Peligro
+settings.site=Sitio Oficial
+settings.update_settings=Actualizar Configuración
+settings.change_reponame=Nombre del Repositorio Modificado
+settings.change_reponame_desc=El nombre del repositorio ha sido modificado, ¿quieres continuar? Esto afectará a todos los enlaces relacionados con este repositorio.
+settings.transfer=Transferir la Propiedad
+settings.transfer_desc=Transferir este repositorio a otro usuario u organización donde tengas permisos de administración.
+settings.new_owner_has_same_repo=El nuevo propietario tiene un repositorio con el mismo nombre.
+settings.delete=Eliminar este Repositorio
+settings.delete_desc=Una vez has eliminado un repositorio, no hay vuelta atrás. Por favor, asegúrate de que es lo que quieres.
+settings.transfer_notices=<p>- Perderás acceso si el nuevo propietario es un usuario individual.</p><p>- Seguirás teniendo acceso si el nuevo propietario es una organización y estás en el grupo de los propietarios.</p>
+settings.update_settings_success=Las opciones del repositorio se han actualizado correctamente.
+settings.transfer_owner=Nuevo Propietario
+settings.make_transfer=Transferir
+settings.transfer_succeed=La propiedad del repositorio ha sido transferida exitosamente.
+settings.confirm_delete=Confirmar Eliminación
+settings.add_collaborator=Añadir Nuevo Colaborador
+settings.add_collaborator_success=Se ha añadido el nuevo colaborador.
+settings.remove_collaborator_success=Se ha eliminado el colaborador.
+settings.user_is_org_member=El usuario es miembro de la organización, no puede ser añadido como colaborador.
+settings.add_webhook=Añadir Webhook
+settings.hooks_desc=Los Webhooks permiten a servicios externos recibir notificaciones cuando sucedan ciertos eventos en Gogs. Cuando sucedan los eventos especificados, enviaremos una petición POST a cada una de las URLs indicadas. Para obtener más información, consulta nuestra <a target="_blank" href="%s">Guía de Webhooks</a>.
+settings.githooks_desc=Los Git Hooks son una funcionalidad del propio Git, puedes editar los ficheros de los hooks soportados en la siguiente lista para aplicar operaciones personalizadas.
+settings.githook_edit_desc=Si el hook no está activo, se mostrará contenido de ejemplo. Dejar el contenido vacío deshabilitará este hook.
+settings.githook_name=Nombre del Hook
+settings.githook_content=Contenido del Hook
+settings.update_githook=Actualizar Hook
+settings.remove_hook_success=El Webhook ha sido eliminado.
+settings.add_webhook_desc=Enviaremos una petición <code>POST</code> a la siguiente URL con los detalles de cualquier evento suscrito. También puedes especificar qué formato de datos te gustaría recibir (JSON, <code>x-www-form-urlencoded</code>, <em>etc</em>). Puedes encontrar más información en la <a target="_blank" href="%s">Guía de Webhooks</a>.
+settings.payload_url=URL de Payload
+settings.content_type=Tipo de Contenido
+settings.secret=Secreto
+settings.event_desc=¿Qué eventos te gustaría que desencadenasen este webhook?
+settings.event_push_only=Solo el evento <code>push</code>.
+settings.active=Activo
+settings.active_helper=Enviaremos detalles del evento cuando este hook se dispare.
+settings.add_hook_success=Se ha añadido un nuevo webhook.
+settings.update_webhook=Actualizar Webhook
+settings.update_hook_success=Se ha actualizado el Webhook.
+settings.delete_webhook=Borrar Webhook
+settings.recent_deliveries=Envíos Recientes
+settings.hook_type=Tipo de Hook
+settings.add_slack_hook_desc=Añade integración con <a href="%s">Slack</a> a tu repositorio.
+settings.slack_token=Token
+settings.slack_domain=Dominio
+settings.slack_channel=Canal
+
+diff.browse_source=Explorar el Código
+diff.parent=padre
+diff.commit=commit
+diff.data_not_available=Los datos del Diff no están disponibles.
+diff.show_diff_stats=Mostrar Estadísticas de Diff
+diff.stats_desc=Se han <strong>modificado %d ficheros</strong> con <strong>%d adiciones</strong> y <strong>%d borrados</strong>
+diff.bin=BIN
+diff.view_file=Ver Fichero
+
+release.releases=Releases
+release.new_release=Nueva Release
+release.draft=Borrador
+release.prerelease=Pre-Release
+release.stable=Estable
+release.edit=editar
+release.ahead=<strong>%d</strong> commits en %s desde esta release
+release.source_code=Código Fuente
+release.tag_name=Nombre de la etiqueta
+release.target=Destino
+release.tag_helper=Escoge una etiqueta o crea una nueva al publicar.
+release.release_title=Título de la Release
+release.content_with_md=Contenido con formato <a href="%s">Markdown</a>
+release.write=Escribir
+release.preview=Vista Previa
+release.content_placeholder=Escribe algo de contenido
+release.loading=Cargando...
+release.prerelease_desc=Esta es una pre-release
+release.prerelease_helper=Esta release está marcada como no apta para producción.
+release.publish=Publicar Release
+release.save_draft=Guardar Borrador
+release.edit_release=Editar Release
+release.tag_name_already_exist=Ya existe una Release con esta etiqueta.
+
+[org]
+org_name_holder=Nombre de la Organización
+org_name_helper=Los grandes nombres de organizaciones son cortos y memorables.
+org_email_helper=Los correos electrónicos de las organizaciones reciben todas las notificaciones y confirmaciones.
+create_org=Crear Organización
+repo_updated=Actualizado
+people=Personas
+invite_someone=Invitar a alguien
+teams=Equipos
+lower_members=miembros
+lower_repositories=repositorios
+create_new_team=Crear un Nuevo Equipo
+org_desc=Descripción
+team_name=Nombre del Equipo
+team_desc=Descripción
+team_name_helper=Utiliza este nombre para mencionar a este equipo en las conversaciones.
+team_desc_helper=¿En qué consiste este equipo?
+team_permission_desc=¿Qué nivel de permisos debería tener este equipo?
+
+settings=Configuración
+settings.options=Opciones
+settings.full_name=Nombre Completo
+settings.website=Sitio Web
+settings.location=Localización
+settings.update_settings=Actualizar Configuración
+settings.change_orgname=Nombre de la Organización Modificado
+settings.change_orgname_desc=El nombre de la organización ha sido modificado, ¿quieres continuar? Esta acción afectará a todos los enlaces relacionados con esta organización.
+settings.update_setting_success=La configuración de la Organización se ha actualizado correctamente.
+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
+settings.delete_org_desc=Esta organización se va a eliminar permanentemente, ¿quieres continuar?
+settings.hooks_desc=Añadir webhooks que serán ejecutados para <strong>todos los repositorios</strong> de esta organización.
+
+members.public=Público
+members.public_helper=convertir en privado
+members.private=Privado
+members.private_helper=convertir en público
+members.owner=Propietario
+members.member=Miembro
+members.conceal=Ocultar
+members.remove=Eliminar
+members.leave=Abandonar
+members.invite_desc=Comienza a teclear un nombre de usuario para invitar a un nuevo miembro a %s:
+members.invite_now=Invitar
+
+teams.join=Unirse
+teams.leave=Abandonar
+teams.read_access=Acceso de Lectura
+teams.read_access_helper=Este equipo podrá ver y clonar sus repositorios.
+teams.write_access=Acceso de Escritura
+teams.write_access_helper=Este equipo podrá leer sus repositorios, así como hacer push en ellos.
+teams.admin_access=Acceso de Administrador
+teams.admin_access_helper=Este equipo podrá hacer push/pull en sus repositorios, así como añadir colaboradores a ellos.
+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.delete_team=Borrar este Equipo
+teams.add_team_member=Añadir Miembro al Equipo
+teams.delete_team_title=Eliminar Equipo
+teams.delete_team_desc=Este equipo va a ser eliminado, ¿seguro que quieres continuar? Los miembros de este equipo pueden perder acceso a algunos repositorios.
+teams.delete_team_success=El Equipo se ha eliminado correctamente.
+teams.read_permission_desc=Este equipo tiene permisos de <strong>Lectura</strong>: sus miembros pueden ver y clonar los repositorios del equipo.
+teams.write_permission_desc=Este equipo tiene permisos de <strong>Escritura</strong>: sus miembros pueden leer y hacer push a los repositorios del equipo.
+teams.admin_permission_desc=Este equipo tiene permisos de <strong>Administración</strong>: sus miembros pueden leer, hacer push y añadir colaboradores a los repositorios del equipo.
+teams.repositories=Repositorios del Equipo
+teams.add_team_repository=Añadir Repositorio al Equipo
+teams.remove_repo=Eliminar
+teams.add_nonexistent_repo=El repositorio que estás intentando añadir no existe, por favor, créalo primero.
+
+[admin]
+dashboard=Dashboard
+users=Usuarios
+organizations=Organizaciones
+repositories=Repositorios
+authentication=Autenticaciones
+config=Configuración
+notices=Avisos del Sistema
+monitor=Monitorización
+prev=Anterior
+next=Siguiente
+
+dashboard.statistic=Estadísticas
+dashboard.operations=Operaciones
+dashboard.system_status=Estado del Monitor del Sistema
+dashboard.statistic_info=La base de datos de Gogs contiene <b>%d</b> usuarios, <b>%d</b> organizaciones, <b>%d</b> claves públicas, <b>%d</b> repositorios, <b>%d</b> vigilados, <b>%d</b> destacados, <b>%d</b> acciones, <b>%d</b> accesos, <b>%d</b> incidencias, <b>%d</b> comentarios, <b>%d</b> cuentas de redes sociales, <b>%d</b> seguidores, <b>%d</b> mirrors, <b>%d</b> releases, <b>%d</b> fuentes de login, <b>%d</b> webhooks, <b>%d</b> milestones, <b>%d</b> etiquetas, <b>%d</b> hooks, <b>%d</b> equipos, <b>%d</b> tareas actualizadas, <b>%d</b> adjuntos.
+dashboard.operation_name=Nombre de la Operación
+dashboard.operation_switch=Interruptor
+dashboard.operation_run=Ejecutar
+dashboard.clean_unbind_oauth=Limpiar solicitudes de OAuth sin confirmar
+dashboard.clean_unbind_oauth_success=Las solicitudes de OAuth sin confirmar se han eliminado correctamente.
+dashboard.delete_inactivate_accounts=Eliminar todas las cuentas inactivas
+dashboard.delete_inactivate_accounts_success=Todas las cuentas inactivas se han eliminado correctamente.
+dashboard.delete_repo_archives=Eliminar todos los archivos de repositorios
+dashboard.delete_repo_archives_success=Todos los archivos de repositorios se han eliminado correctamente.
+dashboard.git_gc_repos=Ejecutar la recolección de basura en los repositorios
+dashboard.git_gc_repos_success=Todos los repositorios han ejecutado correctamente el recolector de basuras.
+dashboard.resync_all_sshkeys=Reescribir el fichero '.ssh/authorized_key'(atención: se perderán las claves que no pertenezcan a Gogs)
+dashboard.resync_all_sshkeys_success=Todas las claves públicas se han reescrito correctamente.
+dashboard.resync_all_update_hooks=Rewrite all update hook of repositories (needed when custom config path is changed)
+dashboard.resync_all_update_hooks_success=All repositories' update hook have been rewritten successfully.
+
+dashboard.server_uptime=Uptime 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.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
+dashboard.heap_memory_released=Memoria de Heap Liberada
+dashboard.heap_objects=Objetos en el Heap
+dashboard.bootstrap_stack_usage=Uso de la Pila de Bootstrap
+dashboard.stack_memory_obtained=Memoria de Pila Obtenida
+dashboard.mspan_structures_usage=Uso de Estructuras MSpan
+dashboard.mspan_structures_obtained=Estructuras MSpan Obtenidas
+dashboard.mcache_structures_usage=Uso de estructuras MCache
+dashboard.mcache_structures_obtained=Estructuras MCache Obtenidas
+dashboard.profiling_bucket_hash_table_obtained=Profiling Bucket Hash Table Obtenido
+dashboard.gc_metadata_obtained=Metadatos del Recolector de Basuras Obtenidos
+dashboard.other_system_allocation_obtained=Otros Recursos del Sistema Asignados
+dashboard.next_gc_recycle=Siguiente Reciclado del Recolector de Basuras
+dashboard.last_gc_time=Tiempo desde el Último GC
+dashboard.total_gc_time=Pausa Total por GC
+dashboard.total_gc_pause=Pausa Total por GC
+dashboard.last_gc_pause=Última Pausa por GC
+dashboard.gc_times=GC Times
+
+users.user_manage_panel=User Manage Panel
+users.new_account=Create New Account
+users.name=Name
+users.activated=Activated
+users.admin=Admin
+users.repos=Repos
+users.created=Created
+users.edit=Edit
+users.auth_source=Authorization Source
+users.local=Local
+users.auth_login_name=Authorization Login Name
+users.update_profile_success=Account profile has been updated successfully.
+users.edit_account=Editar Cuenta
+users.is_activated=Esta cuenta está activada
+users.is_admin=This account has administrator permissions
+users.allow_git_hook=This account has permissions to create Git hooks
+users.update_profile=Update Account Profile
+users.delete_account=Delete This Account
+users.still_own_repo=This account still have ownership of repository, you have to delete or transfer them first.
+users.still_has_org=This account still have membership of organization, you have to left or delete them first.
+
+orgs.org_manage_panel=Organization Manage Panel
+orgs.name=Name
+orgs.teams=Teams
+orgs.members=Members
+
+repos.repo_manage_panel=Repository Manage Panel
+repos.owner=Owner
+repos.name=Name
+repos.private=Private
+repos.watches=Watches
+repos.stars=Stars
+repos.issues=Issues
+
+auths.auth_manage_panel=Authorization Manage Panel
+auths.new=Add New Authorization Source
+auths.name=Name
+auths.type=Type
+auths.enabled=Enabled
+auths.updated=Updated
+auths.auth_type=Authorization Type
+auths.auth_name=Authorization Name
+auths.domain=Domain
+auths.host=Host
+auths.port=Port
+auths.base_dn=Base DN
+auths.attributes=Search Attributes
+auths.filter=Search Filter
+auths.ms_ad_sa=Ms Ad SA
+auths.smtp_auth=SMTP Authorization Type
+auths.smtphost=SMTP Host
+auths.smtpport=SMTP Port
+auths.enable_tls=Enable TLS Encryption
+auths.enable_auto_register=Enable Auto Registration
+auths.tips=Consejos
+auths.edit=Editar la Configuración de Autorización
+auths.activated=Esta autenticación ha sido activada
+auths.update_success=La Configuración de Autorización ha sido actualizada correctamente.
+auths.update=Actualizar la Configuración de Autorización
+auths.delete=Eliminar esta Autorización
+auths.delete_auth_title=Eliminación de Autorización
+auths.delete_auth_desc=Se va a eliminar esta autorización, ¿quieres continuar?
+
+config.server_config=Configuración del Servidor
+config.app_name=Nombre de la Aplicación
+config.app_ver=Versión de la Aplicación
+config.app_url=URL de la Aplicación
+config.domain=Dominio
+config.offline_mode=Modo Sin Conexión
+config.disable_router_log=Deshabilitar Log del Router
+config.run_user=Usuario 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
+config.script_type=Tipo de Script
+config.reverse_auth_user=Reverse Authentication User
+config.db_config=Configuración de la Base de Datos
+config.db_type=Tipo
+config.db_host=Host
+config.db_name=Nombre
+config.db_user=Usuario
+config.db_ssl_mode=Modo SSL
+config.db_ssl_mode_helper=(solo para "postgres")
+config.db_path=Ruta
+config.db_path_helper=(solo para "sqlite3")
+config.service_config=Configuración del Servicio
+config.register_email_confirm=Solicitar Confirmación por Correo Electrónico
+config.disable_register=Deshabilitar el Registro
+config.show_registration_button=Mostrar Botón de Registro
+config.require_sign_in_view=Solicitar la Vista de Inicio de Sesión
+config.mail_notify=Notificación por Correo Electrónico
+config.enable_cache_avatar=Activar la Caché de Avatar
+config.active_code_lives=Active Code Lives
+config.reset_password_code_lives=Reset Password Code Lives
+config.webhook_config=Webhook Configuration
+config.task_interval=Task Interval
+config.deliver_timeout=Deliver Timeout
+config.skip_tls_verify=Skip TLS Verify
+config.mailer_config=Mailer Configuration
+config.mailer_enabled=Enabled
+config.mailer_name=Name
+config.mailer_host=Host
+config.mailer_user=User
+config.oauth_config=OAuth Configuration
+config.oauth_enabled=Enabled
+config.cache_config=Cache Configuration
+config.cache_adapter=Cache Adapter
+config.cache_interval=Cache Interval
+config.cache_conn=Cache Connection
+config.session_config=Session Configuration
+config.session_provider=Session Provider
+config.provider_config=Provider Config
+config.cookie_name=Cookie Name
+config.enable_set_cookie=Enable Set Cookie
+config.gc_interval_time=GC Interval Time
+config.session_life_time=Session Life Time
+config.https_only=HTTPS Only
+config.cookie_life_time=Cookie Life Time
+config.picture_config=Picture Configuration
+config.picture_service=Picture Service
+config.disable_gravatar=Disable Gravatar
+config.log_config=Log Configuration
+config.log_mode=Log Mode
+
+monitor.cron=Cron Tasks
+monitor.name=Name
+monitor.schedule=Schedule
+monitor.next=Next Time
+monitor.previous=Previous Time
+monitor.execute_times=Execute Times
+monitor.process=Running Processes
+monitor.desc=Description
+monitor.start=Start Time
+monitor.execute_time=Execution Time
+
+notices.system_notice_list=System Notices
+notices.type=Type
+notices.type_1=Repository
+notices.desc=Description
+notices.op=Op.
+notices.delete_success=System notice has been deleted successfully.
+
+[action]
+create_repo=created repository <a href="%s/%s">%s</a>
+commit_repo=pushed to <a href="%s/%s/src/%s">%s</a> at <a href="%s/%s">%s</a>
+create_issue=`opened issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
+comment_issue=`commented on issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
+transfer_repo=transfered repository <code>%s</code> to <a href="/%s%s">%s</a>
+push_tag=pushed tag <a href="%s/%s/src/%s">%s</a> to <a href="%s/%s">%s</a>
+compare_2_commits=View comparison for these 2 commits
+
+[tool]
+ago=ago
+from_now=from now
+now=now
+1s=1 second %s
+1m=1 minute %s
+1h=1 hour %s
+1d=1 day %s
+1w=1 week %s
+1mon=1 month %s
+1y=1 year %s
+seconds=%d seconds %s
+minutes=%d minutes %s
+hours=%d hours %s
+days=%d days %s
+weeks=%d weeks %s
+months=%d months %s
+years=%d years %s
+raw_seconds=seconds
+raw_minutes=minutes
+
diff --git a/conf/locale/locale_fr-CA.ini b/conf/locale/locale_fr-CA.ini index ebe74e19..e744b9d9 100755 --- a/conf/locale/locale_fr-CA.ini +++ b/conf/locale/locale_fr-CA.ini @@ -59,6 +59,8 @@ run_user=Entrer un Utilisateur run_user_helper=L'utilisateur doit avoir accès à la Racine du Référentiel et éxécuter Gogs.
domain=Domaine
domain_helper=Cela affecte les doublons d'URL SSH.
+http_port=Port HTTP
+http_port_helper=Numéro de port que l'application écoutera.
app_url=URL de l'Application
app_url_helper=Cela affecte les doublons d'URL HTTP/HTTPS et le contenu d'e-mail.
email_title=Paramètres du Service de Messagerie (Facultatif)
@@ -512,6 +514,11 @@ dashboard.delete_repo_archives=Supprimer toutes les archives de référentiels dashboard.delete_repo_archives_success=Toutes les archives de référentiels ont été supprimés avec succès.
dashboard.git_gc_repos=Collecter les déchets des référentiels
dashboard.git_gc_repos_success=Tous les référentiels ont effectué la collecte avec succès.
+dashboard.resync_all_sshkeys=Ré-écrire le fichier '.ssh/autorized_key' (attention : les clés hors-Gogs vont être perdues)
+dashboard.resync_all_sshkeys_success=Toutes les clés publiques ont été ré-écrites avec succès.
+dashboard.resync_all_update_hooks=Ré-écrire tous les hooks de mises à jour des dépôts (requis quand le chemin de la configuration personnalisé est modifié)
+dashboard.resync_all_update_hooks_success=Tous les hooks de mises à jour des dépôts ont été ré-écris avec succès.
+
dashboard.server_uptime=Durée de Marche Serveur
dashboard.current_goroutine=Goroutines actuelles
dashboard.current_memory_usage=Utilisation Mémoire actuelle
@@ -631,6 +638,7 @@ config.db_path_helper=("sqlite3" uniquement) config.service_config=Configuration du Service
config.register_email_confirm=Nécessite une confirmation par courriel
config.disable_register=Désactiver l'Enregistrement
+config.show_registration_button=Afficher le bouton d'enregistrement
config.require_sign_in_view=Connexion Obligatoire pour Visualiser
config.mail_notify=Mailer les Notifications
config.enable_cache_avatar=Activer le Cache d'Avatar
@@ -639,6 +647,7 @@ config.reset_password_code_lives=Réinitialiser le Mot De Passe des Limites de C config.webhook_config=Configuration Webhook
config.task_interval=Intervalles de Tâches
config.deliver_timeout=Expiration d'Envoi
+config.skip_tls_verify=Ne pas vérifier TLS
config.mailer_config=Configuration du Maileur
config.mailer_enabled=Activé
config.mailer_name=Nom
@@ -686,8 +695,8 @@ notices.delete_success=Note système supprimée avec succès. [action]
create_repo=a crée le Référentiel <a href="%s/%s">%s</a>
commit_repo=a soumis à <a href="%s/%s/src/%s">%s</a> chez <a href="%s/%s">%s</a>
-create_issue=a ouvert un problème <a href="%s/%s/issues/%s">%s#%s</a>
-comment_issue=a commenté le problème <a href="%s/%s/issues/%s">%s#%s</a>
+create_issue=`a ouvert un problème <a href="%s/issues/%s">%[1]s#%[2]s</a>`
+comment_issue=`a commenté le problème <a href="%s/issues/%s">%[1]s#%[2]s</a>`
transfer_repo=a transféré le Référentiel <code>%s</code> à <a href="/%s%s">%s</a>
push_tag=a tagé <a href="%s/%s/src/%s">%s</a> à <a href="%s/%s">%s</a>
compare_2_commits=Comparer ces 2 commissions
@@ -713,16 +722,3 @@ years=%d ans %s raw_seconds=secondes
raw_minutes=minutes
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/conf/locale/locale_ja-JP.ini b/conf/locale/locale_ja-JP.ini index a64ed007..441da8fe 100755 --- a/conf/locale/locale_ja-JP.ini +++ b/conf/locale/locale_ja-JP.ini @@ -516,6 +516,9 @@ dashboard.git_gc_repos=リポジトリでのガベージコレクションを実 dashboard.git_gc_repos_success=すべてのリポジトリは正常にガベージ コレクションを行いました。
dashboard.resync_all_sshkeys='.ssh/ autorized_key' ファイルを再生成します。(警告:Gogsキー以外は失われます)
dashboard.resync_all_sshkeys_success=すべての公開鍵が正常に書き換えられました。
+dashboard.resync_all_update_hooks=リポジトリの update フックをすべて再更新する(カスタムの設定パスが変更されたときに必要)
+dashboard.resync_all_update_hooks_success=リポジトリの update フックがすべて正常に再更新されました。
+
dashboard.server_uptime=サーバーの稼働時間
dashboard.current_goroutine=現在のGoroutine
dashboard.current_memory_usage=現在のメモリ使用量
@@ -644,6 +647,7 @@ config.reset_password_code_lives=パスワードリンクの有効期限をリ config.webhook_config=Webhook設定
config.task_interval=タスクの間隔
config.deliver_timeout=送信タイムアウト
+config.skip_tls_verify=TLSの確認を省略
config.mailer_config=メーラーの構成
config.mailer_enabled=有効にした
config.mailer_name=名前
@@ -691,8 +695,8 @@ notices.delete_success=システム通知が正常に削除されました。 [action]
create_repo=リポジトリ <a href="%s/%s"> %s</a>を作成しました
commit_repo=<a href="%s/%s">%s</a>を<a href="%s/%s/src/%s">%s</a>にプッシュしました
-create_issue=問題 <a href="%s/%s/issues/%s"> %s #%s</a> を開きました
-comment_issue=問題 <a href="%s/%s/issues/%s"> %s #%s</a> のコメント
+create_issue=`問題 <a href="%s/issues/%s">%[1]s#%[2]s</a> を開きました`
+comment_issue=`問題 <a href="%s/issues/%s">%[1]s#%[2]s</a> のコメント`
transfer_repo=リポジトリ <code>%s</code> を <a href="/%s%s">%s</a> へ転送しました
push_tag=<a href="%s/%s">%s</a> に タグ <a href="%s/%s/src/%s">%s</a> をプッシュしました
compare_2_commits=これら 2 のコミットの比較を閲覧する
diff --git a/conf/locale/locale_lv-LV.ini b/conf/locale/locale_lv-LV.ini index 266c3e63..b640972c 100755 --- a/conf/locale/locale_lv-LV.ini +++ b/conf/locale/locale_lv-LV.ini @@ -59,6 +59,8 @@ run_user=Izpildes lietotājs run_user_helper=Lietotājam ir jābūt rakstīšanas tiesībām repozitorija saknes direktorijai un Gogs jābūt palaistam zem šī lietotāja.
domain=Domēns
domain_helper=Tas ietekmē SSH klonēšanas URL.
+http_port=HTTP ports
+http_port_helper=Porta numurs pēc kura lietojumprogrammai būs iespējams pieslēgties.
app_url=Lietotnes URL
app_url_helper=Tas ietekmē HTTP/HTTPS klonēšanas URL un e-pasta saturā izsūtītās saites.
email_title=E-pasta pakalpojuma iestatījumi (neobligāti)
@@ -512,6 +514,11 @@ dashboard.delete_repo_archives=Dzēst visu repozitoriju arhīvus dashboard.delete_repo_archives_success=Visu repozitoriju arhīvi tika veiksmīgi izdzēsti.
dashboard.git_gc_repos=Veikt repozitoriju datu sakārtošānu (git gc)
dashboard.git_gc_repos_success=Datu sakārtošana visiem repozitorijiem veiksmīgi pabeigta.
+dashboard.resync_all_sshkeys=Pārrakstīt '.ssh/authorized_key' failu (brīdinājums: ne-Git atslēgas tiks pazaudētas)
+dashboard.resync_all_sshkeys_success=Visas publiskās atslēgas tika veiksmīgi pārrakstītas.
+dashboard.resync_all_update_hooks=Rewrite all update hook of repositories (needed when custom config path is changed)
+dashboard.resync_all_update_hooks_success=All repositories' update hook have been rewritten successfully.
+
dashboard.server_uptime=Servera darbības laiks
dashboard.current_goroutine=Izmantotās Gorutīnas
dashboard.current_memory_usage=Pašreiz izmantotā atmiņa
@@ -631,7 +638,7 @@ config.db_path_helper=(tikai Sqlite3 datu bāzei) config.service_config=Pakalpojuma konfigurācija
config.register_email_confirm=Pieprasīt e-pasta apstiprināšanu
config.disable_register=Atspējot jaunu lietotāju reģistrāciju
-config.show_registration_button =
+config.show_registration_button=Rādīt reģistrēšanās pogu
config.require_sign_in_view=Nepieciešama autorizācija
config.mail_notify=Pasta paziņojumi
config.enable_cache_avatar=Glabāt profila attēlus kešatmiņā
@@ -640,6 +647,7 @@ config.reset_password_code_lives=Paroles atiestatīšanas koda ilgums config.webhook_config=Tīkla āķu konfigurācija
config.task_interval=Uzdevuma intervāls
config.deliver_timeout=Piegādes noildze
+config.skip_tls_verify=Skip TLS Verify
config.mailer_config=Sūtītāja konfigurācija
config.mailer_enabled=Iespējots
config.mailer_name=Nosaukums
@@ -687,8 +695,8 @@ notices.delete_success=Sistēmas paziņojums tika veiksmīgi izdzēsts. [action]
create_repo=izveidoja repozitoriju <a href="%s/%s">%s</a>
commit_repo=veica izmaiņu nosūtīšanu atzaram <a href="%s/%s/src/%s">%s</a> repozitorijā <a href="%s/%s">%s</a>
-create_issue=reģistrēja problēmu <a href="%s/%s/issues/%s">%s#%s</a>
-comment_issue=pievienoja komentāru problēmai <a href="%s/%s/issues/%s">%s#%s</a>
+create_issue=`reģistrēja problēmu <a href="%s/issues/%s">%[1]s#%[2]s</a>`
+comment_issue=`pievienoja komentāru problēmai <a href="%s/issues/%s">%[1]s#%[2]s</a>`
transfer_repo=mainīja repozitorija <code>%s</code> īpašnieku uz <a href="/%s%s">%s</a>
push_tag=pievienoja tagu <a href="%s/%s/src/%s">%s</a> repozitorijam <a href="%s/%s">%s</a>
compare_2_commits=Veikt salīdzināšanu starp šīm 2 revīzijām
@@ -714,16 +722,3 @@ years=%d gadi %s raw_seconds=sekundes
raw_minutes=minūtes
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/conf/locale/locale_nl-NL.ini b/conf/locale/locale_nl-NL.ini index 414eb1ff..0a4ecb43 100755 --- a/conf/locale/locale_nl-NL.ini +++ b/conf/locale/locale_nl-NL.ini @@ -516,6 +516,9 @@ dashboard.git_gc_repos=Garbage collectie uitvoeren dashboard.git_gc_repos_success=Garbage collectie met succes uitgevoerd.
dashboard.resync_all_sshkeys=Herschrijf '.ssh/authorized_keys' (Let op: alle sleutels die niet van Gogs zijn zullen verloren gaan!)
dashboard.resync_all_sshkeys_success=Alle publieke sleutels zijn herschreven.
+dashboard.resync_all_update_hooks=Herschrijf alle repositorie-hooks (nodig als de configuratie bestandslocatie is gewijzigd)
+dashboard.resync_all_update_hooks_success=Alle repositorie-hooks zijn herschreven.
+
dashboard.server_uptime=Uptime server
dashboard.current_goroutine=Huidige Goroutines
dashboard.current_memory_usage=Huidige geheugen gebruik
@@ -644,6 +647,7 @@ config.reset_password_code_lives=Reset wachtwoord Code leven config.webhook_config=Webhook configuratie
config.task_interval=Taakinterval
config.deliver_timeout=Bezorging verlooptijd
+config.skip_tls_verify=TLS certificaat controle overslaan
config.mailer_config=Mailerconfiguatie
config.mailer_enabled=Ingeschakeld
config.mailer_name=Naam
@@ -691,8 +695,8 @@ notices.delete_success=Systeem bericht is met succes verwijderd. [action]
create_repo=repositorie aangemaakt in <a href="%s/%s">%s</a>
commit_repo=push update naar <a href="%s/%s/src/%s">%s</a> in <a href="%s/%s">%s</a
-create_issue=opende issue in <a href="%s/%s/issues/%s">%s#%s</a>
-comment_issue=reactie op issue <a href="%s/%s/issues/%s">%s#%s</a>
+create_issue=`opende issue in <a href="%s/issues/%s">%[1]s#%[2]s</a>`
+comment_issue=`reactie op issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
transfer_repo=repositorie verplaatst naar <code>%s</code> naar <a href="/%s%s">%s</a>
push_tag=geduwd label <a href="%s/%s/src/%s"> %s</a> naar <a href="%s/%s"> %s</a>
compare_2_commits=Weergave vergelijking voor deze 2 commits
diff --git a/conf/locale/locale_ru-RU.ini b/conf/locale/locale_ru-RU.ini index dfb5870d..e21dca14 100755 --- a/conf/locale/locale_ru-RU.ini +++ b/conf/locale/locale_ru-RU.ini @@ -58,9 +58,11 @@ repo_path_helper=Всех удаленные репозитории Git буде run_user=Пользователь
run_user_helper=У пользователя должен быть доступ к пути к корню репозитория и к запуску Gogs.
domain=Домен
-domain_helper=This affects SSH clone URLs.
+domain_helper=Влияет на URL-адреса для клонирования по SSH.
+http_port=Порт HTTP
+http_port_helper=Номер порта, который приложение будет слушать.
app_url=URL приложения
-app_url_helper=This affects HTTP/HTTPS clone URL and somewhere in e-mail.
+app_url_helper=Этот параметр влияет на URL для клонирования по HTTP/HTTPS и на адреса в электронной почте.
email_title=Настройки службы электронной почты (опционально)
smtp_host=Узел SMTP
mailer_user=Электронная почта отправителя
@@ -78,7 +80,7 @@ test_git_failed=Не удалось проверить 'git' команду: %v sqlite3_not_available=Ваша версия не поддерживает SQLite3, пожалуйста скачайте официальную бинарную версию от %s, а не версию gobuild.
invalid_db_setting=Настройки базы данных не правильные: %v
invalid_repo_path=Недопустимый путь к корню репозитория: %v
-run_user_not_match=Run user isn't the current user: %s -> %s
+run_user_not_match=Текущий пользователь не является пользователем для запуска: %s -> %s
save_config_failed=Не удалось сохранить конфигурацию: %v
invalid_admin_setting=Указан недопустимый параметр учетной записи администратора: %v
install_success=Добро пожаловать! Мы рады, что вы выбрали Gogs. Веселитесь и берегите себя.
@@ -86,7 +88,7 @@ install_success=Добро пожаловать! Мы рады, что вы вы [home]
uname_holder=Имя пользователь или E-mail
password_holder=Пароль
-switch_dashboard_context=Switch Dashboard Context
+switch_dashboard_context=Переключить контекст панели управления
my_repos=Мои репозитории
collaborative_repos=Совместные репозитории
my_orgs=Моя Организация
@@ -278,9 +280,9 @@ license_helper=Выберите файл лицензии init_readme=Создать репозиторий с файлом README.md
create_repo=Создание репозитория
default_branch=Ветка по умолчанию
-mirror_interval=Mirror Interval(hour)
-goget_meta=Go-Get Meta
-goget_meta_helper=This repository will be <span class="label label-blue label-radius">Go-Getable</span>
+mirror_interval=Интервал зеркалирования (час)
+goget_meta=Meta-тег для go get
+goget_meta_helper=Репозиторий будет доступен для <span class="label label-blue label-radius">go get</span>
need_auth=Требуется авторизация
migrate_type=Тип миграции
@@ -512,6 +514,11 @@ dashboard.delete_repo_archives=Удаление всех архивов репо dashboard.delete_repo_archives_success=Все архивы репозиториев были успешно удалены.
dashboard.git_gc_repos=Выполнить сборку мусора на репозиториях
dashboard.git_gc_repos_success=Сборка мусора на всех репозиториях успешно выполнена.
+dashboard.resync_all_sshkeys=Rewrite '.ssh/autorized_key' file (caution: non-Gogs keys will be lost)
+dashboard.resync_all_sshkeys_success=All public keys have been rewritten successfully.
+dashboard.resync_all_update_hooks=Rewrite all update hook of repositories (needed when custom config path is changed)
+dashboard.resync_all_update_hooks_success=All repositories' update hook have been rewritten successfully.
+
dashboard.server_uptime=Время непрерывной работы сервера
dashboard.current_goroutine=Current Goroutines
dashboard.current_memory_usage=Текущее использование памяти
@@ -631,7 +638,7 @@ config.db_path_helper=(for "sqlite3" only) config.service_config=Service Configuration
config.register_email_confirm=Require E-mail Confirmation
config.disable_register=Отключить регистрацию
-config.show_registration_button = Показать Регистрация Кнопка
+config.show_registration_button=Show Register Button
config.require_sign_in_view=Для просмотра необходима авторизация
config.mail_notify=Почтовые уведомления
config.enable_cache_avatar=Кешировать аватар
@@ -640,6 +647,7 @@ config.reset_password_code_lives=Reset Password Code Lives config.webhook_config=Настройка автоматического обновления репозиции
config.task_interval=Интервал задания
config.deliver_timeout=Задержка доставки
+config.skip_tls_verify=Skip TLS Verify
config.mailer_config=Настройки почты
config.mailer_enabled=Включено
config.mailer_name=Имя
@@ -687,8 +695,8 @@ notices.delete_success=System notice has been deleted successfully. [action]
create_repo=создан репозиторий <a href="%s/%s"> %s</a>
commit_repo=pushed to <a href="%s/%s/src/%s">%s</a> at <a href="%s/%s">%s</a>
-create_issue=opened issue <a href="%s/%s/issues/%s">%s#%s</a>
-comment_issue=commented on issue <a href="%s/%s/issues/%s">%s#%s</a>
+create_issue=`opened issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
+comment_issue=`commented on issue <a href="%s/issues/%s">%[1]s#%[2]s</a>`
transfer_repo=transfered repository <code>%s</code> to <a href="/%s%s">%s</a>
push_tag=pushed tag <a href="%s/%s/src/%s">%s</a> to <a href="%s/%s">%s</a>
compare_2_commits=View comparison for these 2 commits
@@ -714,16 +722,3 @@ years=%d years %s raw_seconds=seconds
raw_minutes=minutes
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/conf/locale/locale_zh-CN.ini b/conf/locale/locale_zh-CN.ini index e188a648..35370682 100755 --- a/conf/locale/locale_zh-CN.ini +++ b/conf/locale/locale_zh-CN.ini @@ -516,6 +516,9 @@ dashboard.git_gc_repos=对仓库进行垃圾回收 dashboard.git_gc_repos_success=所有仓库垃圾回收成功!
dashboard.resync_all_sshkeys=重新生成 '.ssh/autorized_key' 文件(警告:不是 Gogs 的密钥也会被删除)
dashboard.resync_all_sshkeys_success=所有公钥重新生成成功!
+dashboard.resync_all_update_hooks=重新生成所有仓库的 Update 钩子(用于自定义配置文件被修改)
+dashboard.resync_all_update_hooks_success=所有仓库的 Update 钩子重新生成成功!
+
dashboard.server_uptime=服务运行时间
dashboard.current_goroutine=当前 Goroutines 数量
dashboard.current_memory_usage=当前内存使用量
@@ -644,6 +647,7 @@ config.reset_password_code_lives=重置密码链接有效期 config.webhook_config=Web 钩子配置
config.task_interval=任务周期
config.deliver_timeout=推送超时
+config.skip_tls_verify=忽略 TLS 验证
config.mailer_config=邮件配置
config.mailer_enabled=启用服务
config.mailer_name=发送者名称
@@ -691,8 +695,8 @@ notices.delete_success=系统提示删除成功! [action]
create_repo=创建了仓库 <a href="%s/%s">%s</a>
commit_repo=推送了 <a href="%s/%s/src/%s">%s</a> 分支的代码到 <a href="%s/%s">%s</a>
-create_issue=创建了工单 <a href="%s/%s/issues/%s">%s#%s</a>
-comment_issue=评论了工单 <a href="%s/%s/issues/%s">%s#%s</a>
+create_issue=`创建了工单 <a href="%s/issues/%s">%[1]s#%[2]s</a>`
+comment_issue=`评论了工单 <a href="%s/issues/%s">%[1]s#%[2]s</a>`
transfer_repo=将仓库 <code>%s</code> 转移至 <a href="/%s%s">%s</a>
push_tag=推送了标签 <a href="%s/%s/src/%s">%s</a> 到 <a href="%s/%s">%s</a>
compare_2_commits=查看 2 次提交的内容对比
diff --git a/conf/locale/locale_zh-HK.ini b/conf/locale/locale_zh-HK.ini index 2fa83789..a9b51a5b 100755 --- a/conf/locale/locale_zh-HK.ini +++ b/conf/locale/locale_zh-HK.ini @@ -516,6 +516,9 @@ dashboard.git_gc_repos=對倉庫進行垃圾回收 dashboard.git_gc_repos_success=所有倉庫的垃圾回收已成功完成!
dashboard.resync_all_sshkeys=重新生成 '.ssh/autorized_key' 文件(警告:不是 Gogs 的密鑰也會被刪除)
dashboard.resync_all_sshkeys_success=所有公鑰重新生成成功!
+dashboard.resync_all_update_hooks=Rewrite all update hook of repositories (needed when custom config path is changed)
+dashboard.resync_all_update_hooks_success=All repositories' update hook have been rewritten successfully.
+
dashboard.server_uptime=服務執行時間
dashboard.current_goroutine=當前 Goroutines 數量
dashboard.current_memory_usage=當前內存使用量
@@ -644,6 +647,7 @@ config.reset_password_code_lives=重置密碼連結有效期 config.webhook_config=Web 鉤子配置
config.task_interval=任務周期
config.deliver_timeout=推送超時
+config.skip_tls_verify=Skip TLS Verify
config.mailer_config=郵件配置
config.mailer_enabled=啟用服務
config.mailer_name=發送者名稱
@@ -691,8 +695,8 @@ notices.delete_success=系統提示刪除成功! [action]
create_repo=創建了倉庫 <a href="%s/%s">%s</a>
commit_repo=推送了 <a href="%s/%s/src/%s">%s</a> 分支的代碼到 <a href="%s/%s">%s</a>
-create_issue=創建了問題 <a href="%s/%s/issues/%s">%s#%s</a>
-comment_issue=評論了問題 <a href="%s/%s/issues/%s">%s#%s</a>
+create_issue=`創建了問題 <a href="%s/issues/%s">%[1]s#%[2]s</a>`
+comment_issue=`評論了問題 <a href="%s/issues/%s">%[1]s#%[2]s</a>`
transfer_repo=將倉庫 <code>%s</code> 轉移至 <a href="/%s%s">%s</a>
push_tag=推送了標籤 <a href="%s/%s/src/%s">%s</a> 到 <a href="%s/%s">%s</a>
compare_2_commits=查看 2 次提交的內容對比
diff --git a/docker/blocks/docker_gogs/Dockerfile b/docker/blocks/docker_gogs/Dockerfile index 2c98cc50..efedc31a 100644 --- a/docker/blocks/docker_gogs/Dockerfile +++ b/docker/blocks/docker_gogs/Dockerfile @@ -4,7 +4,7 @@ FROM ubuntu:14.04 RUN apt-get update && apt-get install -y \ build-essential ca-certificates curl \ - bzr git mercurial \ + bzr git mercurial openssh-client\ --no-install-recommends ENV GOLANG_VERSION 1.3 diff --git a/docker/blocks/docker_gogs_dev/Dockerfile b/docker/blocks/docker_gogs_dev/Dockerfile index 2a628c2d..ce653fbe 100644 --- a/docker/blocks/docker_gogs_dev/Dockerfile +++ b/docker/blocks/docker_gogs_dev/Dockerfile @@ -5,7 +5,7 @@ FROM ubuntu:14.04 RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ apt-get install -qy \ build-essential ca-certificates curl \ - bzr git mercurial \ + bzr git mercurial openssh-client\ --no-install-recommends ENV GOLANG_VERSION 1.3 diff --git a/docker/templates/init_gogs.sh.tpl b/docker/templates/init_gogs.sh.tpl index 26cff4e5..ada11f95 100644 --- a/docker/templates/init_gogs.sh.tpl +++ b/docker/templates/init_gogs.sh.tpl @@ -1,6 +1,6 @@ #!/bin/sh -if [ ! -d "$DIRECTORY" ]; then +if [ ! -d "$GOGS_CUSTOM_CONF_PATH" ]; then mkdir -p $GOGS_CUSTOM_CONF_PATH echo " @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.5.13.0207 Beta" +const APP_VER = "0.5.14.0222 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) @@ -33,7 +33,6 @@ func main() { cmd.CmdWeb, cmd.CmdServ, cmd.CmdUpdate, - cmd.CmdFix, cmd.CmdDump, cmd.CmdCert, } diff --git a/models/action.go b/models/action.go index a6c6cfbf..5cba2f51 100644 --- a/models/action.go +++ b/models/action.go @@ -98,7 +98,7 @@ func (a Action) GetRepoName() string { } func (a Action) GetRepoLink() string { - return path.Join(a.RepoUserName, a.RepoName) + return path.Join(setting.AppSubUrl, a.RepoUserName, a.RepoName) } func (a Action) GetBranch() string { diff --git a/models/git_diff.go b/models/git_diff.go index 7e91626f..9d34ed62 100644 --- a/models/git_diff.go +++ b/models/git_diff.go @@ -60,6 +60,8 @@ type DiffFile struct { Index int Addition, Deletion int Type int + IsCreated bool + IsDeleted bool IsBin bool Sections []*DiffSection } @@ -181,10 +183,16 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff switch { case strings.HasPrefix(scanner.Text(), "new file"): curFile.Type = DIFF_FILE_ADD + curFile.IsDeleted = false + curFile.IsCreated = true case strings.HasPrefix(scanner.Text(), "deleted"): curFile.Type = DIFF_FILE_DEL + curFile.IsCreated = false + curFile.IsDeleted = true case strings.HasPrefix(scanner.Text(), "index"): curFile.Type = DIFF_FILE_CHANGE + curFile.IsCreated = false + curFile.IsDeleted = false } if curFile.Type > 0 { break diff --git a/models/issue.go b/models/issue.go index d9a24063..226ca3ca 100644 --- a/models/issue.go +++ b/models/issue.go @@ -561,7 +561,7 @@ func GetLabels(repoId int64) ([]*Label, error) { // UpdateLabel updates label information. func UpdateLabel(l *Label) error { - _, err := x.Id(l.Id).Update(l) + _, err := x.Id(l.Id).AllCols().Update(l) return err } diff --git a/models/models.go b/models/models.go index df030e51..486aceac 100644 --- a/models/models.go +++ b/models/models.go @@ -15,7 +15,7 @@ import ( "github.com/go-xorm/xorm" _ "github.com/lib/pq" - "github.com/gogits/gogs/models/migrations" + // "github.com/gogits/gogs/models/migrations" "github.com/gogits/gogs/modules/setting" ) @@ -23,7 +23,10 @@ import ( type Engine interface { Delete(interface{}) (int64, error) Exec(string, ...interface{}) (sql.Result, error) + Get(interface{}) (bool, error) Insert(...interface{}) (int64, error) + Id(interface{}) *xorm.Session + Where(string, ...interface{}) *xorm.Session } var ( @@ -118,7 +121,7 @@ func SetEngine() (err error) { if err != nil { return fmt.Errorf("models.init(fail to create xorm.log): %v", err) } - x.Logger = xorm.NewSimpleLogger(f) + x.SetLogger(xorm.NewSimpleLogger(f)) x.ShowSQL = true x.ShowInfo = true @@ -133,9 +136,9 @@ func NewEngine() (err error) { return err } - if err = migrations.Migrate(x); err != nil { - return err - } + // if err = migrations.Migrate(x); err != nil { + // return err + // } if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil { return fmt.Errorf("sync database struct error: %v\n", err) diff --git a/models/org.go b/models/org.go index 5431a111..b2f9c903 100644 --- a/models/org.go +++ b/models/org.go @@ -12,7 +12,6 @@ import ( "strings" "github.com/Unknwon/com" - "github.com/go-xorm/xorm" "github.com/gogits/gogs/modules/base" ) @@ -94,7 +93,7 @@ func CreateOrganization(org, owner *User) (*User, error) { return nil, ErrUserNameIllegal } - isExist, err := IsUserExist(org.Name) + isExist, err := IsUserExist(0, org.Name) if err != nil { return nil, err } else if isExist { @@ -391,7 +390,7 @@ func RemoveOrgUser(orgId, uid int64) error { return err } for _, t := range ts { - if err = removeTeamMemberWithSess(org.Id, t.Id, u.Id, sess); err != nil { + if err = removeTeamMember(sess, org.Id, t.Id, u.Id); err != nil { return err } } @@ -486,18 +485,18 @@ func (t *Team) RemoveMember(uid int64) error { } // addAccessWithAuthorize inserts or updates access with given mode. -func addAccessWithAuthorize(sess *xorm.Session, access *Access, mode AccessType) error { - has, err := x.Get(access) +func addAccessWithAuthorize(e Engine, access *Access, mode AccessType) error { + has, err := e.Get(access) if err != nil { return fmt.Errorf("fail to get access: %v", err) } access.Mode = mode if has { - if _, err = sess.Id(access.Id).Update(access); err != nil { + if _, err = e.Id(access.Id).Update(access); err != nil { return fmt.Errorf("fail to update access: %v", err) } } else { - if _, err = sess.Insert(access); err != nil { + if _, err = e.Insert(access); err != nil { return fmt.Errorf("fail to insert access: %v", err) } } @@ -536,7 +535,7 @@ func (t *Team) AddRepository(repo *Repository) (err error) { mode := AuthorizeToAccessType(t.Authorize) for _, u := range t.Members { - auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, t.Id) + auth, err := getHighestAuthorize(sess, t.OrgId, u.Id, repo.Id, t.Id) if err != nil { sess.Rollback() return err @@ -552,7 +551,7 @@ func (t *Team) AddRepository(repo *Repository) (err error) { return err } } - if err = WatchRepo(u.Id, repo.Id, true); err != nil { + if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { sess.Rollback() return err } @@ -593,7 +592,7 @@ func (t *Team) RemoveRepository(repoId int64) error { // Remove access to team members. for _, u := range t.Members { - auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, t.Id) + auth, err := getHighestAuthorize(sess, t.OrgId, u.Id, repo.Id, t.Id) if err != nil { sess.Rollback() return err @@ -607,7 +606,7 @@ func (t *Team) RemoveRepository(repoId int64) error { if _, err = sess.Delete(access); err != nil { sess.Rollback() return fmt.Errorf("fail to delete access: %v", err) - } else if err = WatchRepo(u.Id, repo.Id, false); err != nil { + } else if err = watchRepo(sess, u.Id, repo.Id, false); err != nil { sess.Rollback() return err } @@ -678,10 +677,9 @@ func GetTeam(orgId int64, name string) (*Team, error) { return t, nil } -// GetTeamById returns team by given ID. -func GetTeamById(teamId int64) (*Team, error) { +func getTeamById(e Engine, teamId int64) (*Team, error) { t := new(Team) - has, err := x.Id(teamId).Get(t) + has, err := e.Id(teamId).Get(t) if err != nil { return nil, err } else if !has { @@ -690,9 +688,13 @@ func GetTeamById(teamId int64) (*Team, error) { return t, nil } -// GetHighestAuthorize returns highest repository authorize level for given user and team. -func GetHighestAuthorize(orgId, uid, repoId, teamId int64) (AuthorizeType, error) { - ts, err := GetUserTeams(orgId, uid) +// GetTeamById returns team by given ID. +func GetTeamById(teamId int64) (*Team, error) { + return getTeamById(x, teamId) +} + +func getHighestAuthorize(e Engine, orgId, uid, repoId, teamId int64) (AuthorizeType, error) { + ts, err := getUserTeams(e, orgId, uid) if err != nil { return 0, err } @@ -714,6 +716,11 @@ func GetHighestAuthorize(orgId, uid, repoId, teamId int64) (AuthorizeType, error return auth, nil } +// GetHighestAuthorize returns highest repository authorize level for given user and team. +func GetHighestAuthorize(orgId, uid, repoId, teamId int64) (AuthorizeType, error) { + return getHighestAuthorize(x, orgId, uid, repoId, teamId) +} + // UpdateTeam updates information of team. func UpdateTeam(t *Team, authChanged bool) (err error) { if !IsLegalName(t.Name) { @@ -866,10 +873,14 @@ type TeamUser struct { TeamId int64 } +func isTeamMember(e Engine, orgId, teamId, uid int64) bool { + has, _ := e.Where("uid=?", uid).And("org_id=?", orgId).And("team_id=?", teamId).Get(new(TeamUser)) + return has +} + // IsTeamMember returns true if given user is a member of team. func IsTeamMember(orgId, teamId, uid int64) bool { - has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).And("team_id=?", teamId).Get(new(TeamUser)) - return has + return isTeamMember(x, orgId, teamId, uid) } // GetTeamMembers returns all members in given team of organization. @@ -879,17 +890,16 @@ func GetTeamMembers(orgId, teamId int64) ([]*User, error) { return us, err } -// GetUserTeams returns all teams that user belongs to in given organization. -func GetUserTeams(orgId, uid int64) ([]*Team, error) { +func getUserTeams(e Engine, orgId, uid int64) ([]*Team, error) { tus := make([]*TeamUser, 0, 5) - if err := x.Where("uid=?", uid).And("org_id=?", orgId).Find(&tus); err != nil { + if err := e.Where("uid=?", uid).And("org_id=?", orgId).Find(&tus); err != nil { return nil, err } ts := make([]*Team, len(tus)) for i, tu := range tus { t := new(Team) - has, err := x.Id(tu.TeamId).Get(t) + has, err := e.Id(tu.TeamId).Get(t) if err != nil { return nil, err } else if !has { @@ -900,6 +910,11 @@ func GetUserTeams(orgId, uid int64) ([]*Team, error) { return ts, nil } +// GetUserTeams returns all teams that user belongs to in given organization. +func GetUserTeams(orgId, uid int64) ([]*Team, error) { + return getUserTeams(x, orgId, uid) +} + // AddTeamMember adds new member to given team of given organization. func AddTeamMember(orgId, teamId, uid int64) error { if IsTeamMember(orgId, teamId, uid) { @@ -956,7 +971,7 @@ func AddTeamMember(orgId, teamId, uid int64) error { // Give access to team repositories. mode := AuthorizeToAccessType(t.Authorize) for _, repo := range t.Repos { - auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, teamId) + auth, err := getHighestAuthorize(sess, t.OrgId, u.Id, repo.Id, teamId) if err != nil { sess.Rollback() return err @@ -993,13 +1008,13 @@ func AddTeamMember(orgId, teamId, uid int64) error { return sess.Commit() } -func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) error { - if !IsTeamMember(orgId, teamId, uid) { +func removeTeamMember(e Engine, orgId, teamId, uid int64) error { + if !isTeamMember(e, orgId, teamId, uid) { return nil } // Get team and its repositories. - t, err := GetTeamById(teamId) + t, err := getTeamById(e, teamId) if err != nil { return err } @@ -1033,19 +1048,16 @@ func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) erro TeamId: teamId, } - if _, err := sess.Delete(tu); err != nil { - sess.Rollback() + if _, err := e.Delete(tu); err != nil { return err - } else if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { - sess.Rollback() + } else if _, err = e.Id(t.Id).AllCols().Update(t); err != nil { return err } // Delete access to team repositories. for _, repo := range t.Repos { - auth, err := GetHighestAuthorize(t.OrgId, u.Id, repo.Id, teamId) + auth, err := getHighestAuthorize(e, t.OrgId, u.Id, repo.Id, teamId) if err != nil { - sess.Rollback() return err } @@ -1055,17 +1067,14 @@ func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) erro } // Delete access if this is the last team user belongs to. if auth == 0 { - if _, err = sess.Delete(access); err != nil { - sess.Rollback() + if _, err = e.Delete(access); err != nil { return fmt.Errorf("fail to delete access: %v", err) - } else if err = WatchRepo(u.Id, repo.Id, false); err != nil { - sess.Rollback() + } else if err = watchRepo(e, u.Id, repo.Id, false); err != nil { return err } } else if auth < t.Authorize { // Downgrade authorize level. - if err = addAccessWithAuthorize(sess, access, AuthorizeToAccessType(auth)); err != nil { - sess.Rollback() + if err = addAccessWithAuthorize(e, access, AuthorizeToAccessType(auth)); err != nil { return err } } @@ -1073,17 +1082,15 @@ func removeTeamMemberWithSess(orgId, teamId, uid int64, sess *xorm.Session) erro // This must exist. ou := new(OrgUser) - _, err = sess.Where("uid=?", uid).And("org_id=?", org.Id).Get(ou) + _, err = e.Where("uid=?", uid).And("org_id=?", org.Id).Get(ou) if err != nil { - sess.Rollback() return err } ou.NumTeams-- if t.IsOwnerTeam() { ou.IsOwner = false } - if _, err = sess.Id(ou.Id).AllCols().Update(ou); err != nil { - sess.Rollback() + if _, err = e.Id(ou.Id).AllCols().Update(ou); err != nil { return err } return nil @@ -1096,7 +1103,8 @@ func RemoveTeamMember(orgId, teamId, uid int64) error { if err := sess.Begin(); err != nil { return err } - if err := removeTeamMemberWithSess(orgId, teamId, uid, sess); err != nil { + if err := removeTeamMember(sess, orgId, teamId, uid); err != nil { + sess.Rollback() return err } return sess.Commit() diff --git a/models/publickey.go b/models/publickey.go index 67ab4242..383b85b6 100644 --- a/models/publickey.go +++ b/models/publickey.go @@ -29,7 +29,7 @@ import ( const ( // "### autogenerated by gitgos, DO NOT EDIT\n" - _TPL_PUBLICK_KEY = `command="%s serv key-%d",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` + "\n" + _TPL_PUBLICK_KEY = `command="%s serv key-%d --config='%s'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` + "\n" ) var ( @@ -98,7 +98,7 @@ func (k *PublicKey) OmitEmail() string { // GetAuthorizedString generates and returns formatted public key string for authorized_keys file. func (key *PublicKey) GetAuthorizedString() string { - return fmt.Sprintf(_TPL_PUBLICK_KEY, appPath, key.Id, key.Content) + return fmt.Sprintf(_TPL_PUBLICK_KEY, appPath, key.Id, setting.CustomConf, key.Content) } var ( diff --git a/models/repo.go b/models/repo.go index 3e07adba..179120a3 100644 --- a/models/repo.go +++ b/models/repo.go @@ -30,7 +30,7 @@ import ( ) const ( - TPL_UPDATE_HOOK = "#!/usr/bin/env %s\n%s update $1 $2 $3\n" + _TPL_UPDATE_HOOK = "#!/usr/bin/env %s\n%s update $1 $2 $3 --config='%s'\n" ) var ( @@ -154,7 +154,6 @@ type Repository struct { IsPrivate bool IsBare bool - IsGoget bool IsMirror bool *Mirror `xorm:"-"` @@ -357,13 +356,16 @@ func MigrateRepository(u *User, name, desc string, private, mirror bool, url str os.RemoveAll(repoPath) } - // this command could for both migrate and mirror + // 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", url, repoPath) if err != nil { - return repo, errors.New("git clone: " + stderr) + return repo, fmt.Errorf("git clone --mirror --bare: %v", stderr) + } else if err = createUpdateHook(repoPath); err != nil { + return repo, fmt.Errorf("create update hook: %v", err) } + return repo, UpdateRepository(repo) } @@ -402,15 +404,9 @@ func initRepoCommit(tmpPath string, sig *git.Signature) (err error) { return nil } -func createHookUpdate(hookPath, content string) error { - pu, err := os.OpenFile(hookPath, os.O_CREATE|os.O_WRONLY, 0777) - if err != nil { - return err - } - defer pu.Close() - - _, err = pu.WriteString(content) - return err +func createUpdateHook(repoPath string) error { + return ioutil.WriteFile(path.Join(repoPath, "hooks/update"), + []byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+appPath+"\"", setting.CustomConf)), 0777) } // InitRepository initializes README and .gitignore if needed. @@ -422,9 +418,7 @@ func initRepository(f string, u *User, repo *Repository, initReadme bool, repoLa return err } - // hook/post-update - if err := createHookUpdate(filepath.Join(repoPath, "hooks", "update"), - fmt.Sprintf(TPL_UPDATE_HOOK, setting.ScriptType, "\""+appPath+"\"")); err != nil { + if err := createUpdateHook(repoPath); err != nil { return err } @@ -1174,6 +1168,18 @@ func DeleteRepositoryArchives() error { }) } +// RewriteRepositoryUpdateHook rewrites all repositories' update hook. +func RewriteRepositoryUpdateHook() error { + return x.Where("id > 0").Iterate(new(Repository), + func(idx int, bean interface{}) error { + repo := bean.(*Repository) + if err := repo.GetOwner(); err != nil { + return err + } + return createUpdateHook(RepoPath(repo.Owner.Name, repo.Name)) + }) +} + var ( // Prevent duplicate tasks. isMirrorUpdating = false @@ -1289,7 +1295,7 @@ func IsWatching(uid, repoId int64) bool { return has } -func watchRepoWithEngine(e Engine, uid, repoId int64, watch bool) (err error) { +func watchRepo(e Engine, uid, repoId int64, watch bool) (err error) { if watch { if IsWatching(uid, repoId) { return nil @@ -1312,7 +1318,7 @@ func watchRepoWithEngine(e Engine, uid, repoId int64, watch bool) (err error) { // Watch or unwatch repository. func WatchRepo(uid, repoId int64, watch bool) (err error) { - return watchRepoWithEngine(x, uid, repoId, watch) + return watchRepo(x, uid, repoId, watch) } // GetWatchers returns all watchers of given repository. @@ -1500,14 +1506,14 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (*Repositor log.Error(4, "GetMembers: %v", err) } else { for _, u := range t.Members { - if err = watchRepoWithEngine(sess, u.Id, repo.Id, true); err != nil { + if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { log.Error(4, "WatchRepo2: %v", err) } } } } } else { - if err = watchRepoWithEngine(sess, u.Id, repo.Id, true); err != nil { + if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { log.Error(4, "WatchRepo3: %v", err) } } diff --git a/models/user.go b/models/user.go index 2da0881c..a974e081 100644 --- a/models/user.go +++ b/models/user.go @@ -249,11 +249,13 @@ func (u *User) GetFullNameFallback() string { // IsUserExist checks if given user name exist, // the user name should be noncased unique. -func IsUserExist(name string) (bool, error) { +// If uid is presented, then check will rule out that one, +// it is used when update a user name in settings page. +func IsUserExist(uid int64, name string) (bool, error) { if len(name) == 0 { return false, nil } - return x.Get(&User{LowerName: strings.ToLower(name)}) + return x.Where("id!=?", uid).Get(&User{LowerName: strings.ToLower(name)}) } // IsEmailUsed returns true if the e-mail has been used. @@ -278,7 +280,7 @@ func CreateUser(u *User) error { return ErrUserNameIllegal } - isExist, err := IsUserExist(u.Name) + isExist, err := IsUserExist(0, u.Name) if err != nil { return err } else if isExist { @@ -397,6 +399,10 @@ func ChangeUserName(u *User, newUserName string) (err error) { } newUserName = strings.ToLower(newUserName) + if u.LowerName == newUserName { + // User only change letter cases. + return nil + } // Update accesses of user. accesses := make([]Access, 0, 10) @@ -453,7 +459,7 @@ func ChangeUserName(u *User, newUserName string) (err error) { // UpdateUser updates user's information. func UpdateUser(u *User) error { - has, err := x.Where("id!=?", u.Id).And("type=?", INDIVIDUAL).And("email=?", u.Email).Get(new(User)) + has, err := x.Where("id!=?", u.Id).And("type=?", u.Type).And("email=?", u.Email).Get(new(User)) if err != nil { return err } else if has { @@ -627,7 +633,7 @@ func GetUserIdsByNames(names []string) []int64 { return ids } -// Get all email addresses +// GetEmailAddresses returns all e-mail addresses belongs to given user. func GetEmailAddresses(uid int64) ([]*EmailAddress, error) { emails := make([]*EmailAddress, 0, 5) err := x.Where("uid=?", uid).Find(&emails) @@ -641,7 +647,6 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) { } isPrimaryFound := false - for _, email := range emails { if email.Email == u.Email { isPrimaryFound = true @@ -654,7 +659,11 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) { // We alway want the primary email address displayed, even if it's not in // the emailaddress table (yet) if !isPrimaryFound { - emails = append(emails, &EmailAddress{Email: u.Email, IsActivated: true, IsPrimary: true}) + emails = append(emails, &EmailAddress{ + Email: u.Email, + IsActivated: true, + IsPrimary: true, + }) } return emails, nil } diff --git a/models/webhook.go b/models/webhook.go index 8e112ac5..96af0b69 100644 --- a/models/webhook.go +++ b/models/webhook.go @@ -5,6 +5,7 @@ package models import ( + "crypto/tls" "encoding/json" "errors" "io/ioutil" @@ -307,13 +308,14 @@ func DeliverHooks() { defer func() { isShooting = false }() tasks := make([]*HookTask, 0, 10) - timeout := time.Duration(setting.WebhookDeliverTimeout) * time.Second + timeout := time.Duration(setting.Webhook.DeliverTimeout) * time.Second x.Where("is_delivered=?", false).Iterate(new(HookTask), func(idx int, bean interface{}) error { t := bean.(*HookTask) req := httplib.Post(t.Url).SetTimeout(timeout, timeout). Header("X-Gogs-Delivery", t.Uuid). - Header("X-Gogs-Event", string(t.EventType)) + Header("X-Gogs-Event", string(t.EventType)). + SetTLSClientConfig(&tls.Config{InsecureSkipVerify: setting.Webhook.SkipTLSVerify}) switch t.ContentType { case JSON: @@ -329,7 +331,7 @@ func DeliverHooks() { case GOGS: { if _, err := req.Response(); err != nil { - log.Error(4, "Delivery: %v", err) + log.Error(5, "Delivery: %v", err) } else { t.IsSucceed = true } @@ -337,15 +339,15 @@ func DeliverHooks() { case SLACK: { if res, err := req.Response(); err != nil { - log.Error(4, "Delivery: %v", err) + log.Error(5, "Delivery: %v", err) } else { defer res.Body.Close() contents, err := ioutil.ReadAll(res.Body) if err != nil { - log.Error(4, "%s", err) + log.Error(5, "%s", err) } else { if string(contents) != "ok" { - log.Error(4, "slack failed with: %s", string(contents)) + log.Error(5, "slack failed with: %s", string(contents)) } else { t.IsSucceed = true } diff --git a/modules/asn1-ber/ber.go b/modules/asn1-ber/ber.go index 3e99a273..52b9a591 100644 --- a/modules/asn1-ber/ber.go +++ b/modules/asn1-ber/ber.go @@ -256,11 +256,11 @@ func ReadPacket(reader io.Reader) (*Packet, error) { } func DecodeString(data []byte) (ret string) { - for _, c := range data { - ret += fmt.Sprintf("%c", c) - } + // for _, c := range data { + // ret += fmt.Sprintf("%c", c) + // } - return + return string(data) } func DecodeInteger(data []byte) (ret uint64) { diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go index 36e62f04..2902a92f 100644 --- a/modules/auth/repo_form.go +++ b/modules/auth/repo_form.go @@ -31,7 +31,7 @@ func (f *CreateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) bin } type MigrateRepoForm struct { - HttpsUrl string `form:"url" binding:"Required;Url"` + CloneAddr string `binding:"Required"` AuthUserName string `form:"auth_username"` AuthPasswd string `form:"auth_password"` Uid int64 `form:"uid" binding:"Required"` @@ -52,7 +52,6 @@ type RepoSettingForm struct { Branch string `form:"branch"` Interval int `form:"interval"` Private bool `form:"private"` - GoGet bool `form:"goget"` } func (f *RepoSettingForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go index 3c0ff651..b616a460 100644 --- a/modules/auth/user_form.go +++ b/modules/auth/user_form.go @@ -99,7 +99,7 @@ func (f *UploadAvatarForm) Validate(ctx *macaron.Context, errs binding.Errors) b } type AddEmailForm struct { - Email string `form:"email" binding:"Required;Email;MaxSize(50)"` + Email string `binding:"Required;Email;MaxSize(50)"` } func (f *AddEmailForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { diff --git a/modules/base/markdown.go b/modules/base/markdown.go index b5f397dc..4a7adc8a 100644 --- a/modules/base/markdown.go +++ b/modules/base/markdown.go @@ -106,7 +106,7 @@ func (options *CustomRender) Image(out *bytes.Buffer, link []byte, title []byte, } var ( - MentionPattern = regexp.MustCompile(`((^|\s)@)[0-9a-zA-Z_]{1,}`) + 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]+`) @@ -128,8 +128,9 @@ func RenderSpecialLink(rawBytes []byte, urlPrefix string) []byte { if !inCodeBlock && !bytes.HasPrefix(line, tab) { ms := MentionPattern.FindAll(line, -1) for _, m := range ms { + m = bytes.TrimSpace(m) line = bytes.Replace(line, m, - []byte(fmt.Sprintf(`<a href="%s/%s">%s</a>`, setting.AppSubUrl, m[2:], m)), -1) + []byte(fmt.Sprintf(`<a href="%s/%s">%s</a>`, setting.AppSubUrl, m[1:], m)), -1) } } diff --git a/modules/base/template.go b/modules/base/template.go index f3fa1385..cfcabb71 100644 --- a/modules/base/template.go +++ b/modules/base/template.go @@ -41,6 +41,10 @@ func List(l *list.List) chan interface{} { return c } +func Sha1(str string) string { + return EncodeSha1(str) +} + func ShortSha(sha1 string) string { if len(sha1) == 40 { return sha1[:10] @@ -126,8 +130,13 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{ return a + b }, "ActionIcon": ActionIcon, - "DateFormat": DateFormat, - "List": List, + "DateFmtLong": func(t time.Time) string { + return t.Format(time.RFC1123Z) + }, + "DateFmtShort": func(t time.Time) string { + return t.Format("Jan 02, 2006") + }, + "List": List, "Mail2Domain": func(mail string) string { if !strings.Contains(mail, "@") { return "try.gogs.io" @@ -155,6 +164,7 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{ }, "DiffTypeToStr": DiffTypeToStr, "DiffLineTypeToStr": DiffLineTypeToStr, + "Sha1": Sha1, "ShortSha": ShortSha, "Md5": EncodeMd5, "ActionContent2Commits": ActionContent2Commits, diff --git a/modules/base/tool.go b/modules/base/tool.go index 5043364c..55e6dffd 100644 --- a/modules/base/tool.go +++ b/modules/base/tool.go @@ -126,7 +126,7 @@ func VerifyTimeLimitCode(data string, minutes int, code string) bool { retCode := CreateTimeLimitCode(data, minutes, start) if retCode == code && minutes > 0 { // check time is expired or not - before, _ := DateParse(start, "YmdHi") + before, _ := time.ParseInLocation("200601021504", start, time.Local) now := time.Now() if before.Add(time.Minute*time.Duration(minutes)).Unix() > now.Unix() { return true @@ -141,7 +141,7 @@ const TimeLimitCodeLength = 12 + 6 + 40 // create a time limit code // code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string { - format := "YmdHi" + format := "200601021504" var start, end time.Time var startStr, endStr string @@ -149,16 +149,16 @@ func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string if startInf == nil { // Use now time create code start = time.Now() - startStr = DateFormat(start, format) + startStr = start.Format(format) } else { // use start string create code startStr = startInf.(string) - start, _ = DateParse(startStr, format) - startStr = DateFormat(start, format) + start, _ = time.ParseInLocation(format, startStr, time.Local) + startStr = start.Format(format) } end = start.Add(time.Minute * time.Duration(minutes)) - endStr = DateFormat(end, format) + endStr = end.Format(format) // create sha1 encode string sh := sha1.New() @@ -420,58 +420,3 @@ func Subtract(left interface{}, right interface{}) interface{} { return fleft + float64(rleft) - (fright + float64(rright)) } } - -// DateFormat pattern rules. -var datePatterns = []string{ - // year - "Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003 - "y", "06", //A two digit representation of a year Examples: 99 or 03 - - // month - "m", "01", // Numeric representation of a month, with leading zeros 01 through 12 - "n", "1", // Numeric representation of a month, without leading zeros 1 through 12 - "M", "Jan", // A short textual representation of a month, three letters Jan through Dec - "F", "January", // A full textual representation of a month, such as January or March January through December - - // day - "d", "02", // Day of the month, 2 digits with leading zeros 01 to 31 - "j", "2", // Day of the month without leading zeros 1 to 31 - - // week - "D", "Mon", // A textual representation of a day, three letters Mon through Sun - "l", "Monday", // A full textual representation of the day of the week Sunday through Saturday - - // time - "g", "3", // 12-hour format of an hour without leading zeros 1 through 12 - "G", "15", // 24-hour format of an hour without leading zeros 0 through 23 - "h", "03", // 12-hour format of an hour with leading zeros 01 through 12 - "H", "15", // 24-hour format of an hour with leading zeros 00 through 23 - - "a", "pm", // Lowercase Ante meridiem and Post meridiem am or pm - "A", "PM", // Uppercase Ante meridiem and Post meridiem AM or PM - - "i", "04", // Minutes with leading zeros 00 to 59 - "s", "05", // Seconds, with leading zeros 00 through 59 - - // time zone - "T", "MST", - "P", "-07:00", - "O", "-0700", - - // RFC 2822 - "r", time.RFC1123Z, -} - -// Parse Date use PHP time format. -func DateParse(dateString, format string) (time.Time, error) { - replacer := strings.NewReplacer(datePatterns...) - format = replacer.Replace(format) - return time.ParseInLocation(format, dateString, time.Local) -} - -// Date takes a PHP like date func to Go's time format. -func DateFormat(t time.Time, format string) string { - replacer := strings.NewReplacer(datePatterns...) - format = replacer.Replace(format) - return t.Format(format) -} diff --git a/modules/cron/manager.go b/modules/cron/manager.go index 135fec4f..2990ab06 100644 --- a/modules/cron/manager.go +++ b/modules/cron/manager.go @@ -15,7 +15,7 @@ var c = New() func NewCronContext() { c.AddFunc("Update mirrors", "@every 1h", models.MirrorUpdate) - c.AddFunc("Deliver hooks", fmt.Sprintf("@every %dm", setting.WebhookTaskInterval), models.DeliverHooks) + c.AddFunc("Deliver hooks", fmt.Sprintf("@every %dm", setting.Webhook.TaskInterval), models.DeliverHooks) if setting.Git.Fsck.Enable { c.AddFunc("Repository health check", fmt.Sprintf("@every %dh", setting.Git.Fsck.Interval), models.GitFsck) } diff --git a/modules/git/signature.go b/modules/git/signature.go index 20f647d2..ad9c1b39 100644 --- a/modules/git/signature.go +++ b/modules/git/signature.go @@ -17,24 +17,35 @@ type Signature struct { When time.Time } -// Helper to get a signature from the commit line, which looks like this: +// 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! -func newSignatureFromCommitline(line []byte) (*Signature, error) { +// 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]) emailstop := bytes.IndexByte(line, '>') sig.Email = string(line[emailstart+1 : emailstop]) - timestop := bytes.IndexByte(line[emailstop+2:], ' ') - timestring := string(line[emailstop+2 : emailstop+2+timestop]) - seconds, err := strconv.ParseInt(timestring, 10, 64) - if err != nil { - return nil, err + + // Check date format. + firstChar := line[emailstop+2] + if firstChar >= 48 && firstChar <= 57 { + timestop := bytes.IndexByte(line[emailstop+2:], ' ') + timestring := string(line[emailstop+2 : emailstop+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(time.RFC1123Z, string(line[emailstop+2:])) + if err != nil { + return nil, err + } } - sig.When = time.Unix(seconds, 0) return sig, nil } diff --git a/modules/mailer/mailer.go b/modules/mailer/mailer.go index 6a23e5d0..fc6ec2fa 100644 --- a/modules/mailer/mailer.go +++ b/modules/mailer/mailer.go @@ -10,6 +10,7 @@ import ( "net" "net/mail" "net/smtp" + "os" "strings" "github.com/gogits/gogs/modules/log" @@ -95,6 +96,15 @@ func sendMail(settings *setting.Mailer, recipients []string, msgContent []byte) return err } + hostname, err := os.Hostname() + if err != nil { + return err + } + + if err = client.Hello(hostname); err != nil { + return err + } + // If not using SMTPS, alway use STARTTLS if available hasStartTLS, _ := client.Extension("STARTTLS") if !isSecureConn && hasStartTLS { diff --git a/modules/middleware/auth.go b/modules/middleware/auth.go index b0bcd87f..3c06c69f 100644 --- a/modules/middleware/auth.go +++ b/modules/middleware/auth.go @@ -6,7 +6,6 @@ package middleware import ( "net/url" - "strings" "github.com/Unknwon/macaron" "github.com/macaron-contrib/csrf" @@ -50,10 +49,6 @@ func Toggle(options *ToggleOptions) macaron.Handler { if options.SignInRequire { if !ctx.IsSigned { - // Ignore watch repository operation. - if strings.HasSuffix(ctx.Req.RequestURI, "watch") { - return - } ctx.SetCookie("redirect_to", url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl) ctx.Redirect(setting.AppSubUrl + "/user/login") return diff --git a/modules/middleware/context.go b/modules/middleware/context.go index 28be3a30..45779d58 100644 --- a/modules/middleware/context.go +++ b/modules/middleware/context.go @@ -130,6 +130,18 @@ func (ctx *Context) Handle(status int, title string, err error) { ctx.HTML(status, base.TplName(fmt.Sprintf("status/%d", status))) } +func (ctx *Context) HandleAPI(status int, obj interface{}) { + var message string + if err, ok := obj.(error); ok { + message = err.Error() + } else { + message = obj.(string) + } + ctx.JSON(status, map[string]string{ + "message": message, + }) +} + func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) { modtime := time.Now() for _, p := range params { diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go index 1ab158dd..67a9eda6 100644 --- a/modules/middleware/repo.go +++ b/modules/middleware/repo.go @@ -394,8 +394,7 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler { } ctx.Data["CloneLink"] = ctx.Repo.CloneLink - if ctx.Repo.Repository.IsGoget { - ctx.Data["GoGetLink"] = fmt.Sprintf("%s%s/%s", setting.AppUrl, u.LowerName, repo.LowerName) + if ctx.Query("go-get") == "1" { ctx.Data["GoGetImport"] = fmt.Sprintf("%s/%s/%s", setting.Domain, u.LowerName, repo.LowerName) } diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 6a205921..52dca3f0 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -68,8 +68,11 @@ var ( ReverseProxyAuthUser string // Webhook settings. - WebhookTaskInterval int - WebhookDeliverTimeout int + Webhook struct { + TaskInterval int + DeliverTimeout int + SkipTLSVerify bool + } // Repository settings. RepoRootPath string @@ -125,6 +128,7 @@ var ( Cfg *ini.File ConfRootPath string CustomPath string // Custom directory path. + CustomConf string ProdMode bool RunUser string IsWindows bool @@ -173,13 +177,16 @@ func NewConfigContext() { CustomPath = path.Join(workDir, "custom") } - cfgPath := path.Join(CustomPath, "conf/app.ini") - if com.IsFile(cfgPath) { - if err = Cfg.Append(cfgPath); err != nil { - log.Fatal(4, "Fail to load custom 'conf/app.ini': %v", err) + if len(CustomConf) == 0 { + CustomConf = path.Join(CustomPath, "conf/app.ini") + } + + if com.IsFile(CustomConf) { + if err = Cfg.Append(CustomConf); err != nil { + log.Fatal(4, "Fail to load custom conf '%s': %v", CustomConf, err) } } else { - log.Warn("No custom 'conf/app.ini' found, ignore this if you're running first time") + log.Warn("Custom config (%s) not found, ignore this if you're running first time", CustomConf) } Cfg.NameMapper = ini.AllCapsUnderscore @@ -234,6 +241,9 @@ func NewConfigContext() { sec = Cfg.Section("attachment") AttachmentPath = sec.Key("PATH").MustString("data/attachments") + if !filepath.IsAbs(AttachmentPath) { + AttachmentPath = path.Join(workDir, AttachmentPath) + } AttachmentAllowedTypes = sec.Key("ALLOWED_TYPES").MustString("image/jpeg|image/png") AttachmentMaxSize = sec.Key("MAX_SIZE").MustInt64(32) AttachmentMaxFiles = sec.Key("MAX_FILES").MustInt(10) @@ -291,6 +301,9 @@ func NewConfigContext() { sec = Cfg.Section("picture") PictureService = sec.Key("SERVICE").In("server", []string{"server"}) AvatarUploadPath = sec.Key("AVATAR_UPLOAD_PATH").MustString("data/avatars") + if !filepath.IsAbs(AvatarUploadPath) { + AvatarUploadPath = path.Join(workDir, AvatarUploadPath) + } os.MkdirAll(AvatarUploadPath, os.ModePerm) switch sec.Key("GRAVATAR_SOURCE").MustString("gravatar") { case "duoshuo": @@ -504,8 +517,10 @@ func newNotifyMailService() { } func newWebhookService() { - WebhookTaskInterval = Cfg.Section("webhook").Key("TASK_INTERVAL").MustInt(1) - WebhookDeliverTimeout = Cfg.Section("webhook").Key("DELIVER_TIMEOUT").MustInt(5) + sec := Cfg.Section("webhook") + Webhook.TaskInterval = sec.Key("TASK_INTERVAL").MustInt(1) + Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5) + Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool() } func NewServices() { diff --git a/public/ng/css/gogs.css b/public/ng/css/gogs.css index 1db8ee69..43931e94 100644 --- a/public/ng/css/gogs.css +++ b/public/ng/css/gogs.css @@ -1086,6 +1086,7 @@ The register and sign-in page style border-right: none; width: 190px; border-left: none; + cursor: default; } #repo-clone-help { clear: both; @@ -1218,6 +1219,9 @@ The register and sign-in page style #repo-files-table { margin-bottom: 20px; } +#repo-files-table .sha .label { + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; +} #repo-files-table th, #repo-files-table td { text-align: left; diff --git a/public/ng/js/gogs.js b/public/ng/js/gogs.js index a6b9753e..c5fd719c 100644 --- a/public/ng/js/gogs.js +++ b/public/ng/js/gogs.js @@ -209,27 +209,28 @@ var Gogs = {}; $list.parents('tr').removeClass('end-selected-line'); $list.parents('tr').find('td').removeClass('selected-line'); if ($from) { - var expr = new RegExp(/diff-(\d+)L(\d+)/); + var expr = new RegExp(/diff-(\w+)([LR]\d+)/); var selectMatches = $select.attr('rel').match(expr) var fromMatches = $from.attr('rel').match(expr) - var a = parseInt(selectMatches[2]); - var b = parseInt(fromMatches[2]); - var linesIntToStr = {}; - linesIntToStr[a] = selectMatches[2]; - linesIntToStr[b] = fromMatches[2]; - - var c; - if (a != b) { - if (a > b) { - c = a; - a = b; - b = c; + var selectTop = $select.offset().top; + var fromTop = $from.offset().top; + var hash; + + if (selectMatches[2] != fromMatches[2]) { + if ((selectTop > fromTop)) { + $startElem = $from; + $endElem = $select; + hash = fromMatches[1]+fromMatches[2] + '-' + selectMatches[2]; + } else { + $startElem = $select; + $endElem = $from; + hash = selectMatches[1]+selectMatches[2] + '-' + fromMatches[2]; } - $('[rel=diff-'+fromMatches[1]+'L' + linesIntToStr[b] + ']').parents('tr').next().addClass('end-selected-line'); - var $selectedLines = $('[rel=diff-'+fromMatches[1]+'L' + linesIntToStr[a] + ']').parents('tr').nextUntil('.end-selected-line').andSelf(); + $endElem.parents('tr').next().addClass('end-selected-line'); + var $selectedLines = $startElem.parents('tr').nextUntil('.end-selected-line').andSelf(); $selectedLines.find('td.lines-num > span').addClass('active') $selectedLines.find('td').addClass('selected-line'); - $.changeHash('#diff-'+fromMatches[1]+'L' + linesIntToStr[a] + '-L' + linesIntToStr[b]); + $.changeHash('#diff-'+hash); return } } @@ -262,7 +263,7 @@ var Gogs = {}; }); $(window).on('hashchange', function (e) { - var m = window.location.hash.match(/^#diff-(\d+)(L\d+)\-(L\d+)$/); + var m = window.location.hash.match(/^#diff-(\w+)([LR]\d+)\-([LR]\d+)$/); var $list = $('.code-diff td.lines-num > span'); var $first; if (m) { @@ -271,7 +272,7 @@ var Gogs = {}; $("html, body").scrollTop($first.offset().top - 200); return; } - m = window.location.hash.match(/^#diff-(\d+)(L\d+)$/); + m = window.location.hash.match(/^#diff-(\w+)([LR]\d+)$/); if (m) { $first = $list.filter('[rel=diff-' + m[1] + m[2] + ']'); selectRange($list, $first); diff --git a/public/ng/less/gogs/repository.less b/public/ng/less/gogs/repository.less index 09691ee8..63c25d06 100644 --- a/public/ng/less/gogs/repository.less +++ b/public/ng/less/gogs/repository.less @@ -101,6 +101,7 @@ border-right: none; width: 190px; border-left: none; + cursor: default; } #repo-clone-help { clear: both; @@ -247,6 +248,9 @@ } #repo-files-table { margin-bottom: 20px; + .sha .label { + font-family: Monaco,Menlo,Consolas,"Courier New",monospace; + } th, td { text-align: left; line-height: 32px; diff --git a/routers/admin/admin.go b/routers/admin/admin.go index ea50d5c4..316f1d42 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -119,6 +119,7 @@ const ( CLEAN_REPO_ARCHIVES GIT_GC_REPOS SYNC_SSH_AUTHORIZED_KEY + SYNC_REPOSITORY_UPDATE_HOOK ) func Dashboard(ctx *middleware.Context) { @@ -148,6 +149,9 @@ func Dashboard(ctx *middleware.Context) { case SYNC_SSH_AUTHORIZED_KEY: success = ctx.Tr("admin.dashboard.resync_all_sshkeys_success") err = models.RewriteAllPublicKeys() + case SYNC_REPOSITORY_UPDATE_HOOK: + success = ctx.Tr("admin.dashboard.resync_all_update_hooks_success") + err = models.RewriteRepositoryUpdateHook() } if err != nil { @@ -184,11 +188,8 @@ func Config(ctx *middleware.Context) { ctx.Data["ReverseProxyAuthUser"] = setting.ReverseProxyAuthUser ctx.Data["Service"] = setting.Service - ctx.Data["DbCfg"] = models.DbCfg - - ctx.Data["WebhookTaskInterval"] = setting.WebhookTaskInterval - ctx.Data["WebhookDeliverTimeout"] = setting.WebhookDeliverTimeout + ctx.Data["Webhook"] = setting.Webhook ctx.Data["MailerEnabled"] = false if setting.MailService != nil { diff --git a/routers/api/v1/repo.go b/routers/api/v1/repo.go index fbf9c73e..fde184d9 100644 --- a/routers/api/v1/repo.go +++ b/routers/api/v1/repo.go @@ -5,7 +5,7 @@ package v1 import ( - "fmt" + "net/url" "path" "strings" @@ -156,17 +156,15 @@ func CreateOrgRepo(ctx *middleware.Context, opt api.CreateRepoOption) { func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) { u, err := models.GetUserByName(ctx.Query("username")) if err != nil { - ctx.JSON(500, map[string]interface{}{ - "ok": false, - "error": err.Error(), - }) + if err == models.ErrUserNotExist { + ctx.HandleAPI(422, err) + } else { + ctx.HandleAPI(500, err) + } return } if !u.ValidtePassword(ctx.Query("password")) { - ctx.JSON(500, map[string]interface{}{ - "ok": false, - "error": "username or password is not correct", - }) + ctx.HandleAPI(422, "Username or password is not correct.") return } @@ -175,56 +173,59 @@ func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) { if form.Uid != u.Id { org, err := models.GetUserById(form.Uid) if err != nil { - log.Error(4, "GetUserById: %v", err) - ctx.Error(500) + if err == models.ErrUserNotExist { + ctx.HandleAPI(422, err) + } else { + ctx.HandleAPI(500, err) + } return } ctxUser = org } if ctx.HasError() { - ctx.JSON(422, map[string]interface{}{ - "ok": false, - "error": ctx.GetErrMsg(), - }) + ctx.HandleAPI(422, ctx.GetErrMsg()) return } if ctxUser.IsOrganization() { // Check ownership of organization. if !ctxUser.IsOwnedBy(u.Id) { - ctx.JSON(403, map[string]interface{}{ - "ok": false, - "error": "given user is not owner of organization", - }) + ctx.HandleAPI(403, "Given user is not owner of organization.") return } } - authStr := strings.Replace(fmt.Sprintf("://%s:%s", - form.AuthUserName, form.AuthPasswd), "@", "%40", -1) - url := strings.Replace(form.HttpsUrl, "://", authStr+"@", 1) - repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private, - form.Mirror, url) - if err == nil { - log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName) - ctx.JSON(200, map[string]interface{}{ - "ok": true, - "data": "/" + ctxUser.Name + "/" + form.RepoName, - }) + // Remote address can be HTTPS URL or local path. + remoteAddr := form.CloneAddr + if strings.HasPrefix(form.CloneAddr, "http") { + u, err := url.Parse(form.CloneAddr) + if err != nil { + ctx.HandleAPI(422, err) + return + } + if len(form.AuthUserName) > 0 || len(form.AuthPasswd) > 0 { + u.User = url.UserPassword(form.AuthUserName, form.AuthPasswd) + } + remoteAddr = u.String() + } else if !com.IsDir(remoteAddr) { + ctx.HandleAPI(422, "Invalid local path, it does not exist or not a directory.") return } - if repo != nil { - if errDelete := models.DeleteRepository(ctxUser.Id, repo.Id, ctxUser.Name); errDelete != nil { - log.Error(4, "DeleteRepository: %v", errDelete) + repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private, form.Mirror, remoteAddr) + if err != nil { + if repo != nil { + if errDelete := models.DeleteRepository(ctxUser.Id, repo.Id, ctxUser.Name); errDelete != nil { + log.Error(4, "DeleteRepository: %v", errDelete) + } } + ctx.HandleAPI(500, err) + return } - ctx.JSON(500, map[string]interface{}{ - "ok": false, - "error": err.Error(), - }) + log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName) + ctx.WriteHeader(200) } // GET /user/repos diff --git a/routers/install.go b/routers/install.go index 9c3f134d..a7828e35 100644 --- a/routers/install.go +++ b/routers/install.go @@ -9,6 +9,7 @@ import ( "os" "os/exec" "path" + "path/filepath" "strings" "github.com/Unknwon/com" @@ -188,6 +189,12 @@ func InstallPost(ctx *middleware.Context, form auth.InstallForm) { // Save settings. cfg := ini.Empty() + if com.IsFile(setting.CustomConf) { + // Keeps custom settings if there is already something. + if err := cfg.Append(setting.CustomConf); err != nil { + log.Error(4, "Fail to load custom conf '%s': %v", setting.CustomConf, err) + } + } cfg.Section("database").Key("DB_TYPE").SetValue(models.DbCfg.Type) cfg.Section("database").Key("HOST").SetValue(models.DbCfg.Host) cfg.Section("database").Key("NAME").SetValue(models.DbCfg.Name) @@ -221,8 +228,8 @@ func InstallPost(ctx *middleware.Context, form auth.InstallForm) { cfg.Section("security").Key("INSTALL_LOCK").SetValue("true") cfg.Section("security").Key("SECRET_KEY").SetValue(base.GetRandomString(15)) - os.MkdirAll("custom/conf", os.ModePerm) - if err := cfg.SaveTo(path.Join(setting.CustomPath, "conf/app.ini")); err != nil { + os.MkdirAll(filepath.Dir(setting.CustomConf), os.ModePerm) + if err := cfg.SaveTo(setting.CustomConf); err != nil { ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), INSTALL, &form) return } diff --git a/routers/org/setting.go b/routers/org/setting.go index 41ec4a21..c638a032 100644 --- a/routers/org/setting.go +++ b/routers/org/setting.go @@ -39,18 +39,18 @@ func SettingsPost(ctx *middleware.Context, form auth.UpdateOrgSettingForm) { // Check if organization name has been changed. if org.Name != form.OrgUserName { - isExist, err := models.IsUserExist(form.OrgUserName) + isExist, err := models.IsUserExist(org.Id, form.OrgUserName) if err != nil { ctx.Handle(500, "IsUserExist", err) return } else if isExist { + ctx.Data["Err_UserName"] = true ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), SETTINGS_OPTIONS, &form) return } else if err = models.ChangeUserName(org, form.OrgUserName); err != nil { if err == models.ErrUserNameIllegal { - ctx.Flash.Error(ctx.Tr("form.illegal_username")) - ctx.Redirect(setting.AppSubUrl + "/org/" + org.LowerName + "/settings") - return + ctx.Data["Err_UserName"] = true + ctx.RenderWithErr(ctx.Tr("form.illegal_username"), SETTINGS_OPTIONS, &form) } else { ctx.Handle(500, "ChangeUserName", err) } @@ -68,7 +68,12 @@ func SettingsPost(ctx *middleware.Context, form auth.UpdateOrgSettingForm) { org.Avatar = base.EncodeMd5(form.Avatar) org.AvatarEmail = form.Avatar if err := models.UpdateUser(org); err != nil { - ctx.Handle(500, "UpdateUser", err) + if err == models.ErrEmailAlreadyUsed { + ctx.Data["Err_Email"] = true + ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SETTINGS_OPTIONS, &form) + } else { + ctx.Handle(500, "UpdateUser", err) + } return } log.Trace("Organization setting updated: %s", org.Name) diff --git a/routers/org/teams.go b/routers/org/teams.go index 77a7b6e1..9dd9b8e2 100644 --- a/routers/org/teams.go +++ b/routers/org/teams.go @@ -138,11 +138,8 @@ func TeamsRepoAction(ctx *middleware.Context) { } if err != nil { - log.Error(3, "Action(%s): %v", ctx.Params(":action"), err) - ctx.JSON(200, map[string]interface{}{ - "ok": false, - "err": err.Error(), - }) + log.Error(3, "Action(%s): '%s' %v", ctx.Params(":action"), ctx.Org.Team.Name, err) + ctx.Handle(500, "TeamsRepoAction", err) return } ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName + "/repositories") diff --git a/routers/repo/commit.go b/routers/repo/commit.go index e92ec8c8..5d354c4b 100644 --- a/routers/repo/commit.go +++ b/routers/repo/commit.go @@ -253,6 +253,9 @@ func Diff(ctx *middleware.Context) { ctx.Data["Parents"] = parents ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 ctx.Data["SourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", commitId) + if (commit.ParentCount() > 0) { + ctx.Data["BeforeSourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", parents[0]) + } ctx.Data["RawPath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "raw", commitId) ctx.HTML(200, DIFF) } @@ -316,6 +319,7 @@ func CompareDiff(ctx *middleware.Context) { ctx.Data["Diff"] = diff ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 ctx.Data["SourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", afterCommitId) + ctx.Data["BeforeSourcePath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "src", beforeCommitId) ctx.Data["RawPath"] = setting.AppSubUrl + "/" + path.Join(userName, repoName, "raw", afterCommitId) ctx.HTML(200, DIFF) } diff --git a/routers/repo/repo.go b/routers/repo/repo.go index 48f7b09b..dfd827bb 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -181,20 +181,26 @@ func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) { } } - u, err := url.Parse(form.HttpsUrl) - - if err != nil || u.Scheme != "https" { - ctx.Data["Err_HttpsUrl"] = true - ctx.RenderWithErr(ctx.Tr("form.url_error"), MIGRATE, &form) + // Remote address can be HTTPS URL or local path. + remoteAddr := form.CloneAddr + if strings.HasPrefix(form.CloneAddr, "http") { + u, err := url.Parse(form.CloneAddr) + if err != nil { + ctx.Data["Err_CloneAddr"] = true + ctx.RenderWithErr(ctx.Tr("form.url_error"), MIGRATE, &form) + return + } + if len(form.AuthUserName) > 0 || len(form.AuthPasswd) > 0 { + u.User = url.UserPassword(form.AuthUserName, form.AuthPasswd) + } + remoteAddr = u.String() + } else if !com.IsDir(remoteAddr) { + ctx.Data["Err_CloneAddr"] = true + ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), MIGRATE, &form) return } - if len(form.AuthUserName) > 0 || len(form.AuthPasswd) > 0 { - u.User = url.UserPassword(form.AuthUserName, form.AuthPasswd) - } - - repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private, - form.Mirror, u.String()) + repo, err := models.MigrateRepository(ctxUser, form.RepoName, form.Description, form.Private, form.Mirror, remoteAddr) if err == nil { log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName) ctx.Redirect(setting.AppSubUrl + "/" + ctxUser.Name + "/" + form.RepoName) diff --git a/routers/repo/setting.go b/routers/repo/setting.go index 33bf1eab..b40ef2d9 100644 --- a/routers/repo/setting.go +++ b/routers/repo/setting.go @@ -8,9 +8,9 @@ import ( "encoding/json" "errors" "fmt" + "path" "strings" "time" - "path" "github.com/Unknwon/com" @@ -84,7 +84,6 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) { ctx.Repo.Repository.Description = form.Description ctx.Repo.Repository.Website = form.Website ctx.Repo.Repository.IsPrivate = form.Private - ctx.Repo.Repository.IsGoget = form.GoGet if err := models.UpdateRepository(ctx.Repo.Repository); err != nil { ctx.Handle(404, "UpdateRepository", err) return @@ -110,7 +109,7 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) { } newOwner := ctx.Query("new_owner_name") - isExist, err := models.IsUserExist(newOwner) + isExist, err := models.IsUserExist(0, newOwner) if err != nil { ctx.Handle(500, "IsUserExist", err) return diff --git a/routers/user/auth.go b/routers/user/auth.go index 9ed44e35..5dacaf8c 100644 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -351,15 +351,12 @@ func ActivateEmail(ctx *middleware.Context) { // Verify code. if email := models.VerifyActiveEmailCode(code, email_string); email != nil { - err := email.Activate() - if err != nil { + if err := email.Activate(); err != nil { ctx.Handle(500, "ActivateEmail", err) } log.Trace("Email activated: %s", email.Email) - ctx.Flash.Success(ctx.Tr("settings.activate_email_success")) - } ctx.Redirect(setting.AppSubUrl + "/user/settings/email") diff --git a/routers/user/setting.go b/routers/user/setting.go index 953e6113..a44d3b7e 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -50,7 +50,7 @@ func SettingsPost(ctx *middleware.Context, form auth.UpdateProfileForm) { // Check if user name has been changed. if ctx.User.Name != form.UserName { - isExist, err := models.IsUserExist(form.UserName) + isExist, err := models.IsUserExist(ctx.User.Id, form.UserName) if err != nil { ctx.Handle(500, "IsUserExist", err) return @@ -58,11 +58,14 @@ func SettingsPost(ctx *middleware.Context, form auth.UpdateProfileForm) { ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), SETTINGS_PROFILE, &form) return } else if err = models.ChangeUserName(ctx.User, form.UserName); err != nil { - if err == models.ErrUserNameIllegal { + switch err { + case models.ErrUserNameIllegal: ctx.Flash.Error(ctx.Tr("form.illegal_username")) ctx.Redirect(setting.AppSubUrl + "/user/settings") - return - } else { + case models.ErrEmailAlreadyUsed: + ctx.Flash.Error(ctx.Tr("form.email_been_used")) + ctx.Redirect(setting.AppSubUrl + "/user/settings") + default: ctx.Handle(500, "ChangeUserName", err) } return @@ -133,13 +136,12 @@ func SettingsEmails(ctx *middleware.Context) { ctx.Data["PageIsUserSettings"] = true ctx.Data["PageIsSettingsEmails"] = true - var err error - ctx.Data["Emails"], err = models.GetEmailAddresses(ctx.User.Id) - + emails, err := models.GetEmailAddresses(ctx.User.Id) if err != nil { - ctx.Handle(500, "email.GetEmailAddresses", err) + ctx.Handle(500, "GetEmailAddresses", err) return } + ctx.Data["Emails"] = emails ctx.HTML(200, SETTINGS_EMAILS) } @@ -149,16 +151,16 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { ctx.Data["PageIsUserSettings"] = true ctx.Data["PageIsSettingsEmails"] = true - var err error - ctx.Data["Emails"], err = models.GetEmailAddresses(ctx.User.Id) + emails, err := models.GetEmailAddresses(ctx.User.Id) if err != nil { - ctx.Handle(500, "email.GetEmailAddresses", err) + ctx.Handle(500, "GetEmailAddresses", err) return } + ctx.Data["Emails"] = emails - // Delete Email address. + // Delete E-mail address. if ctx.Query("_method") == "DELETE" { - id := com.StrTo(ctx.Query("id")).MustInt64() + id := ctx.QueryInt64("id") if id <= 0 { return } @@ -174,7 +176,7 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { // Make emailaddress primary. if ctx.Query("_method") == "PRIMARY" { - id := com.StrTo(ctx.Query("id")).MustInt64() + id := ctx.QueryInt64("id") if id <= 0 { return } @@ -189,46 +191,41 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { } // Add Email address. - if ctx.Req.Method == "POST" { - if ctx.HasError() { - ctx.HTML(200, SETTINGS_EMAILS) - return - } + if ctx.HasError() { + ctx.HTML(200, SETTINGS_EMAILS) + return + } - cleanEmail := strings.Replace(form.Email, "\n", "", -1) - e := &models.EmailAddress{ - Uid: ctx.User.Id, - Email: cleanEmail, - IsActivated: !setting.Service.RegisterEmailConfirm, - } + cleanEmail := strings.Replace(form.Email, "\n", "", -1) + e := &models.EmailAddress{ + Uid: ctx.User.Id, + Email: cleanEmail, + IsActivated: !setting.Service.RegisterEmailConfirm, + } - if err := models.AddEmailAddress(e); err != nil { - if err == models.ErrEmailAlreadyUsed { - ctx.RenderWithErr(ctx.Tr("form.email_has_been_used"), SETTINGS_EMAILS, &form) - return - } - ctx.Handle(500, "email.AddEmailAddress", err) + if err := models.AddEmailAddress(e); err != nil { + if err == models.ErrEmailAlreadyUsed { + ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SETTINGS_EMAILS, &form) return - } else { - - // Send confirmation e-mail - if setting.Service.RegisterEmailConfirm { - mailer.SendActivateEmail(ctx.Render, ctx.User, e) + } + ctx.Handle(500, "AddEmailAddress", err) + return + } else { + // Send confirmation e-mail + if setting.Service.RegisterEmailConfirm { + mailer.SendActivateEmail(ctx.Render, ctx.User, e) - if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { - log.Error(4, "Set cache(MailResendLimit) fail: %v", err) - } - ctx.Flash.Success(ctx.Tr("settings.add_email_success_confirmation_email_sent")) - } else { - ctx.Flash.Success(ctx.Tr("settings.add_email_success")) + if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { + log.Error(4, "Set cache(MailResendLimit) fail: %v", err) } - - log.Trace("Email address added: %s", e.Email) - - ctx.Redirect(setting.AppSubUrl + "/user/settings/email") - return + ctx.Flash.Success(ctx.Tr("settings.add_email_success_confirmation_email_sent")) + } else { + ctx.Flash.Success(ctx.Tr("settings.add_email_success")) } + log.Trace("Email address added: %s", e.Email) + ctx.Redirect(setting.AppSubUrl + "/user/settings/email") + return } ctx.HTML(200, SETTINGS_EMAILS) diff --git a/scripts/less.sh b/scripts/less.sh new file mode 100755 index 00000000..ff2f5736 --- /dev/null +++ b/scripts/less.sh @@ -0,0 +1,5 @@ +#!/bin/sh +echo "compiling LESS Files" +lessc ../public/ng/less/gogs.less ../public/ng/css/gogs.css +lessc ../public/ng/less/ui.less ../public/ng/css/ui.css +echo "done" diff --git a/templates/.VERSION b/templates/.VERSION index 5a5ed364..b9cd4a18 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.5.13.0207 Beta
\ No newline at end of file +0.5.14.0222 Beta
\ No newline at end of file diff --git a/templates/admin/auth/list.tmpl b/templates/admin/auth/list.tmpl index aba516b8..ec701a8f 100644 --- a/templates/admin/auth/list.tmpl +++ b/templates/admin/auth/list.tmpl @@ -34,8 +34,8 @@ <td><a href="{{AppSubUrl}}/admin/auths/{{.Id}}">{{.Name}}</a></td> <td>{{.TypeString}}</td> <td><i class="fa fa{{if .IsActived}}-check{{end}}-square-o"></i></td> - <td><span title="{{DateFormat .Updated "r"}}">{{DateFormat .Updated "M d, Y"}}</span></td> - <td><span title="{{DateFormat .Created "r"}}">{{DateFormat .Created "M d, Y"}}</span></td> + <td><span title="{{DateFmtLong .Updated}}">{{DateFmtShort .Updated}}</span></td> + <td><span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created}}</span></td> <td><a href="{{AppSubUrl}}/admin/auths/{{.Id}}"><i class="fa fa-pencil-square-o"></i></a></td> </tr> {{end}} diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index f8b4be0b..6c328353 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -102,9 +102,11 @@ <div class="panel-body"> <dl class="dl-horizontal admin-dl-horizontal"> <dt>{{.i18n.Tr "admin.config.task_interval"}}</dt> - <dd>{{.WebhookTaskInterval}} {{.i18n.Tr "tool.raw_minutes"}}</dd> + <dd>{{.Webhook.TaskInterval}} {{.i18n.Tr "tool.raw_minutes"}}</dd> <dt>{{.i18n.Tr "admin.config.deliver_timeout"}}</dt> - <dd>{{.WebhookDeliverTimeout}} {{.i18n.Tr "tool.raw_seconds"}}</dd> + <dd>{{.Webhook.DeliverTimeout}} {{.i18n.Tr "tool.raw_seconds"}}</dd> + <dt>{{.i18n.Tr "admin.config.skip_tls_verify"}}</dt> + <dd><i class="fa fa{{if .Webhook.SkipTLSVerify}}-check{{end}}-square-o"></i></dd> </dl> </div> </div> diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index b5705175..5db717bf 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -52,7 +52,10 @@ <td>{{.i18n.Tr "admin.dashboard.resync_all_sshkeys"}}</td> <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=5">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> </tr> - + <tr> + <td>{{.i18n.Tr "admin.dashboard.resync_all_update_hooks"}}</td> + <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=6">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> + </tr> </tbody> </table> </div> diff --git a/templates/admin/org/list.tmpl b/templates/admin/org/list.tmpl index b522dc08..ce5083a0 100644 --- a/templates/admin/org/list.tmpl +++ b/templates/admin/org/list.tmpl @@ -35,7 +35,7 @@ <td>{{.NumTeams}}</td> <td>{{.NumMembers}}</td> <td>{{.NumRepos}}</td> - <td><span title="{{DateFormat .Created "r"}}">{{DateFormat .Created "M d, Y"}}</span></td> + <td><span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created}}</span></td> </tr> {{end}} </tbody> diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl index 88e16a43..981e2ef7 100644 --- a/templates/admin/repo/list.tmpl +++ b/templates/admin/repo/list.tmpl @@ -37,7 +37,7 @@ <td>{{.NumWatches}}</td> <td>{{.NumStars}}</td> <td>{{.NumIssues}}</td> - <td><span title="{{DateFormat .Created "r"}}">{{DateFormat .Created "M d, Y"}}</span></td> + <td><span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created}}</span></td> </tr> {{end}} </tbody> diff --git a/templates/admin/user/list.tmpl b/templates/admin/user/list.tmpl index d42d5291..1dd5553e 100644 --- a/templates/admin/user/list.tmpl +++ b/templates/admin/user/list.tmpl @@ -37,7 +37,7 @@ <td><i class="fa fa{{if .IsActive}}-check{{end}}-square-o"></i></td> <td><i class="fa fa{{if .IsAdmin}}-check{{end}}-square-o"></i></td> <td>{{.NumRepos}}</td> - <td><span title="{{DateFormat .Created "r"}}">{{DateFormat .Created "M d, Y"}}</span></td> + <td><span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created }}</span></td> <td><a href="{{AppSubUrl}}/admin/users/{{.Id}}"><i class="fa fa-pencil-square-o"></i></a></td> </tr> {{end}} diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index 7775933c..cb3951ea 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -9,7 +9,7 @@ <meta name="description" content="Gogs(Go Git Service) is a GitHub-like clone in the Go Programming Language" /> <meta name="keywords" content="go, git"> <meta name="_csrf" content="{{.CsrfToken}}" /> - {{if .Repository.IsGoget}}<meta name="go-import" content="{{.GoGetImport}} git {{.CloneLink.HTTPS}}">{{end}} + {{if .GoGetImport}}<meta name="go-import" content="{{.GoGetImport}} git {{.CloneLink.HTTPS}}">{{end}} <!-- Stylesheets --> {{if CdnMode}} diff --git a/templates/ng/base/footer.tmpl b/templates/ng/base/footer.tmpl index 734533a1..e152a4de 100644 --- a/templates/ng/base/footer.tmpl +++ b/templates/ng/base/footer.tmpl @@ -1,7 +1,7 @@ </div> <footer id="footer"> <div class="container clear"> - <p class="left" id="footer-rights">© 2014 GoGits · {{.i18n.Tr "version"}}: {{AppVer}} · {{.i18n.Tr "page"}}: <strong>{{LoadTimes .PageStartTime}}</strong> · + <p class="left" id="footer-rights">© 2015 GoGits · {{.i18n.Tr "version"}}: {{AppVer}} · {{.i18n.Tr "page"}}: <strong>{{LoadTimes .PageStartTime}}</strong> · {{.i18n.Tr "template"}}: <strong>{{call .TmplLoadTimes}}</strong></p> <div class="right" id="footer-links"> diff --git a/templates/ng/base/head.tmpl b/templates/ng/base/head.tmpl index 40a7d28f..f2a235bd 100644 --- a/templates/ng/base/head.tmpl +++ b/templates/ng/base/head.tmpl @@ -7,7 +7,7 @@ <meta name="description" content="Gogs(Go Git Service) a painless self-hosted Git Service written in Go" /> <meta name="keywords" content="go, git, self-hosted, gogs"> <meta name="_csrf" content="{{.CsrfToken}}" /> - {{if .Repository.IsGoget}}<meta name="go-import" content="{{.GoGetImport}} git {{.CloneLink.HTTPS}}">{{end}} + {{if .GoGetImport}}<meta name="go-import" content="{{.GoGetImport}} git {{.CloneLink.HTTPS}}">{{end}} <link rel="shortcut icon" href="{{AppSubUrl}}/img/favicon.png" /> diff --git a/templates/org/base/header.tmpl b/templates/org/base/header.tmpl index 1bbb092b..1649b920 100644 --- a/templates/org/base/header.tmpl +++ b/templates/org/base/header.tmpl @@ -2,7 +2,7 @@ <div class="container"> <a class="text-black left" href="{{AppSubUrl}}/org/{{.Org.LowerName}}"> <img class="avatar-48 left" src="{{.Org.AvatarLink}}?s=100"> - <span class="org-name">{{.Org.FullName}}</span> + <span class="org-name">{{if .Org.FullName}}{{.Org.FullName}}{{else}}{{.Org.Name}}{{end}}</span> </a> <ul class="menu menu-line container"> <li class="right"> diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl index bb160b57..df29d61f 100644 --- a/templates/org/home.tmpl +++ b/templates/org/home.tmpl @@ -9,85 +9,85 @@ {{if .IsOrganizationOwner}}<a class="text-grey" href="{{.OrgLink}}/settings"><span class="octicon octicon-gear"></span></a>{{end}} </h2> {{if .Org.Description}}<p>{{.Org.Description}}</p>{{end}} - <ul class="text-grey"> - {{if .Org.Location}}<li><span class="octicon octicon-location"></span> <span>{{.Org.Location}}</span></li>{{end}} - {{if .Org.Website}}<li><span class="octicon octicon-link"></span> <a target="_blank" href="{{.Org.Website}}">{{.Org.Website}}</a></li>{{end}} - {{if .Org.Email}}<li><span class="octicon octicon-mail"></span> <a href="mailto:{{.Org.Email}}">{{.Org.Email}}</a></li>{{end}} - </ul> + <ul class="text-grey"> + {{if .Org.Location}}<li><span class="octicon octicon-location"></span> <span>{{.Org.Location}}</span></li>{{end}} + {{if .Org.Website}}<li><span class="octicon octicon-link"></span> <a target="_blank" href="{{.Org.Website}}">{{.Org.Website}}</a></li>{{end}} + {{if .Org.Email}}<li><span class="octicon octicon-mail"></span> <a href="mailto:{{.Org.Email}}">{{.Org.Email}}</a></li>{{end}} + </ul> </div> </div> </div> <div class="container"> {{$isMember := .Org.IsOrgMember $.SignedUser.Id}} - <div id="org-home-repo-list" class="left grid-2-3"> - <div class="clear"> - {{if .IsOrganizationOwner}} - <a class="btn btn-green btn-large btn-link btn-radius right" href="{{AppSubUrl}}/repo/create?org={{.Org.Id}}"><i class="octicon octicon-repo-create"></i> {{.i18n.Tr "new_repo"}}</a> - {{end}} - </div> - <div id="org-repo-list"> - {{range .Repos}} - {{if .HasAccess $.SignedUser.Name}} - <div class="org-repo-item"> - <ul class="org-repo-status right"> - <li><i class="octicon octicon-star"></i> {{.NumStars}}</li> - <li><i class="octicon octicon-git-branch"></i> {{.NumForks}}</li> - </ul> - <h2><a href="{{AppSubUrl}}/{{$.Org.Name}}/{{.Name}}">{{.Name}}</a></h2> - <p class="org-repo-description">{{.Description}}</p> - <p class="org-repo-updated">{{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Updated $.i18n.Lang}}</p> - </div> - {{end}} + <div id="org-home-repo-list" class="left grid-2-3"> + <div class="clear"> + {{if .IsOrganizationOwner}} + <a class="btn btn-green btn-large btn-link btn-radius right" href="{{AppSubUrl}}/repo/create?org={{.Org.Id}}"><i class="octicon octicon-repo-create"></i> {{.i18n.Tr "new_repo"}}</a> + {{end}} + </div> + <div id="org-repo-list"> + {{range .Repos}} + {{if or (not .IsPrivate) (.HasAccess $.SignedUser.Name)}} + <div class="org-repo-item"> + <ul class="org-repo-status right"> + <li><i class="octicon octicon-star"></i> {{.NumStars}}</li> + <li><i class="octicon octicon-git-branch"></i> {{.NumForks}}</li> + </ul> + <h2><a href="{{AppSubUrl}}/{{$.Org.Name}}/{{.Name}}">{{.Name}}</a></h2> + <p class="org-repo-description">{{.Description}}</p> + <p class="org-repo-updated">{{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Updated $.i18n.Lang}}</p> + </div> {{end}} - </div> + {{end}} </div> - <div class="grid-1-3 right"> - <div class="org-sidebar"> - <div class="panel panel-radius"> - <div class="panel-header"> - {{if $isMember}} - <a class="text-grey right" href="{{AppSubUrl}}/org/{{.Org.LowerName}}/members"><strong>{{.Org.NumMembers}}</strong><span class="octicon octicon-chevron-right"></span></a> - {{end}} - <strong>{{.i18n.Tr "org.people"}}</strong> - </div> - <div class="panel-body member-avatar-group"> - {{range .Members}} + </div> + <div class="grid-1-3 right"> + <div class="org-sidebar"> + <div class="panel panel-radius"> + <div class="panel-header"> + {{if $isMember}} + <a class="text-grey right" href="{{AppSubUrl}}/org/{{.Org.LowerName}}/members"><strong>{{.Org.NumMembers}}</strong><span class="octicon octicon-chevron-right"></span></a> + {{end}} + <strong>{{.i18n.Tr "org.people"}}</strong> + </div> + <div class="panel-body member-avatar-group"> + {{range .Members}} {{if or $isMember (.IsPublicMember $.Org.Id)}} - <a href="{{AppSubUrl}}/{{.Name}}" title="{{.Name}}"><img src="{{.AvatarLink}}"></a> - {{end}} + <a href="{{AppSubUrl}}/{{.Name}}" title="{{.Name}}"><img src="{{.AvatarLink}}"></a> {{end}} - </div> - {{if .IsOrganizationOwner}} - <div class="panel-footer"> - <a class="btn btn-medium btn-blue btn-link btn-radius" href="{{AppSubUrl}}/org/{{.Org.LowerName}}/invitations/new">{{.i18n.Tr "org.invite_someone"}}</a> - </div> - {{end}} - </div> - {{if $isMember}} - <br> - <div class="panel panel-radius"> - <div class="panel-header"> - <a class="text-grey right" href="{{AppSubUrl}}/org/{{.Org.LowerName}}/teams"><strong>{{.Org.NumTeams}}</strong><span class="octicon octicon-chevron-right"></span></a> - <strong>{{.i18n.Tr "org.teams"}}</strong> - </div> - <div class="panel-body" id="org-home-team-list"> - <ul> - {{range .Teams}} - <li> - <a class="text-black" href="{{AppSubUrl}}/org/{{$.Org.LowerName}}/teams/{{.LowerName}}"><strong class="team-name">{{.Name}}</strong></a> - <p class="team-meta">{{.NumMembers}} {{$.i18n.Tr "org.lower_members"}} · {{.NumRepos}} {{$.i18n.Tr "org.lower_repositories"}}</p> - </li> - {{end}} - </ul> - </div> - {{if .IsOrganizationOwner}} - <div class="panel-footer"> - <a class="btn btn-medium btn-blue btn-link btn-radius" href="{{AppSubUrl}}/org/{{$.Org.LowerName}}/teams/new">{{.i18n.Tr "org.create_new_team"}}</a> - </div> - {{end}} - </div> - {{end}} + {{end}} + </div> + {{if .IsOrganizationOwner}} + <div class="panel-footer"> + <a class="btn btn-medium btn-blue btn-link btn-radius" href="{{AppSubUrl}}/org/{{.Org.LowerName}}/invitations/new">{{.i18n.Tr "org.invite_someone"}}</a> + </div> + {{end}} </div> - </div> + {{if $isMember}} + <br> + <div class="panel panel-radius"> + <div class="panel-header"> + <a class="text-grey right" href="{{AppSubUrl}}/org/{{.Org.LowerName}}/teams"><strong>{{.Org.NumTeams}}</strong><span class="octicon octicon-chevron-right"></span></a> + <strong>{{.i18n.Tr "org.teams"}}</strong> + </div> + <div class="panel-body" id="org-home-team-list"> + <ul> + {{range .Teams}} + <li> + <a class="text-black" href="{{AppSubUrl}}/org/{{$.Org.LowerName}}/teams/{{.LowerName}}"><strong class="team-name">{{.Name}}</strong></a> + <p class="team-meta">{{.NumMembers}} {{$.i18n.Tr "org.lower_members"}} · {{.NumRepos}} {{$.i18n.Tr "org.lower_repositories"}}</p> + </li> + {{end}} + </ul> + </div> + {{if .IsOrganizationOwner}} + <div class="panel-footer"> + <a class="btn btn-medium btn-blue btn-link btn-radius" href="{{AppSubUrl}}/org/{{$.Org.LowerName}}/teams/new">{{.i18n.Tr "org.create_new_team"}}</a> + </div> + {{end}} + </div> + {{end}} + </div> + </div> </div> {{template "ng/base/footer" .}}
\ No newline at end of file diff --git a/templates/org/settings/nav.tmpl b/templates/org/settings/nav.tmpl index 11d32d7f..1285c4ab 100644 --- a/templates/org/settings/nav.tmpl +++ b/templates/org/settings/nav.tmpl @@ -1,12 +1,12 @@ <div id="setting-menu" class="grid-1-5 panel panel-radius left"> - <div class="panel-header"> - <strong>{{.i18n.Tr "org.settings"}}</strong> - </div> - <div class="panel-body"> - <ul class="menu menu-vertical switching-list grid-1-5 left"> - <li {{if .PageIsSettingsOptions}}class="current"{{end}}><a href="{{AppSubUrl}}/org/{{.Org.LowerName}}/settings">{{.i18n.Tr "org.settings.options"}}</a></li> - <li {{if .PageIsSettingsHooks}}class="current"{{end}}><a href="{{AppSubUrl}}/org/{{.Org.LowerName}}/settings/hooks">{{.i18n.Tr "repo.settings.hooks"}}</a></li> - <li {{if .PageIsSettingsDelete}}class="current"{{end}}><a href="{{AppSubUrl}}/org/{{.Org.LowerName}}/settings/delete">{{.i18n.Tr "org.settings.delete"}}</a></li> - </ul> - </div> + <div class="panel-header"> + <strong>{{.i18n.Tr "org.settings"}}</strong> + </div> + <div class="panel-body"> + <ul class="menu menu-vertical switching-list grid-1-5 left"> + <li {{if .PageIsSettingsOptions}}class="current"{{end}}><a href="{{AppSubUrl}}/org/{{.Org.Name}}/settings">{{.i18n.Tr "org.settings.options"}}</a></li> + <li {{if .PageIsSettingsHooks}}class="current"{{end}}><a href="{{AppSubUrl}}/org/{{.Org.Name}}/settings/hooks">{{.i18n.Tr "repo.settings.hooks"}}</a></li> + <li {{if .PageIsSettingsDelete}}class="current"{{end}}><a href="{{AppSubUrl}}/org/{{.Org.Name}}/settings/delete">{{.i18n.Tr "org.settings.delete"}}</a></li> + </ul> + </div> </div> diff --git a/templates/org/settings/options.tmpl b/templates/org/settings/options.tmpl index 1ed7acb5..1179ede6 100644 --- a/templates/org/settings/options.tmpl +++ b/templates/org/settings/options.tmpl @@ -2,63 +2,63 @@ {{template "ng/base/header" .}} {{template "org/base/header" .}} <div id="setting-wrapper" class="main-wrapper"> - <div id="org-setting" class="container clear"> - {{template "org/settings/nav" .}} - <div class="grid-4-5 left"> - <div class="setting-content"> - {{template "ng/base/alert" .}} - <div id="setting-content"> - <div id="user-profile-setting-content" class="panel panel-radius"> - <div class="panel-header"> - <strong>{{.i18n.Tr "org.settings.options"}}</strong> - </div> - <form class="form form-align panel-body" id="org-setting-form" action="{{AppSubUrl}}/org/{{.Org.LowerName}}/settings" method="post"> - {{.CsrfTokenHtml}} - <input type="hidden" name="action" value="update"> - <div class="field"> - <label class="req" for="orgname">{{.i18n.Tr "username"}}</label> - <input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="orgname" name="uname" value="{{.Org.Name}}" data-orgname="{{.Org.Name}}" required /> - </div> - <div class="white-popup-block mfp-hide" id="change-orgname-modal"> - <h1 class="text-red">{{.i18n.Tr "org.settings.change_orgname"}}</h1> - <p>{{.i18n.Tr "org.settings.change_orgname_desc"}}</p> - <br> - <button class="btn btn-red btn-large btn-radius" id="change-orgname-submit">{{.i18n.Tr "settings.continue"}}</button> - <button class="btn btn-large btn-radius popup-modal-dismiss">{{.i18n.Tr "settings.cancel"}}</button> - </div> - <div class="field"> - <label for="full-name">{{.i18n.Tr "org.settings.full_name"}}</label> - <input class="ipt ipt-large ipt-radius {{if .Err_FullName}}ipt-error{{end}}" id="full-name" name="fullname" value="{{.Org.FullName}}" /> - </div> - <div class="field"> - <label class="req" for="email">{{.i18n.Tr "email"}}</label> - <input class="ipt ipt-large ipt-radius {{if .Err_Email}}ipt-error{{end}}" id="email" name="email" type="email" value="{{.Org.Email}}" required /> - </div> - <div class="field clear"> - <label class="left" for="desc">{{.i18n.Tr "org.org_desc"}}</label> - <textarea class="ipt ipt-large ipt-radius {{if .Err_Description}}ipt-error{{end}}" id="desc" name="desc">{{.Org.Description}}</textarea> - </div> - <div class="field"> - <label for="website">{{.i18n.Tr "org.settings.website"}}</label> - <input class="ipt ipt-large ipt-radius {{if .Err_Website}}ipt-error{{end}}" id="website" name="website" type="url" value="{{.Org.Website}}" /> - </div> - <div class="field"> - <label for="location">{{.i18n.Tr "org.settings.location"}}</label> - <input class="ipt ipt-large ipt-radius {{if .Err_Location}}ipt-error{{end}}" id="location" name="location" type="text" value="{{.Org.Location}}" /> - </div> - <div class="field"> - <label for="gravatar-email">Gravatar {{.i18n.Tr "email"}}</label> - <input class="ipt ipt-large ipt-radius {{if .Err_Avatar}}ipt-error{{end}}" id="gravatar-email" name="avatar" type="text" value="{{.Org.AvatarEmail}}" /> - </div> - <div class="field"> - <span class="form-label"></span> - <button class="btn btn-green btn-large btn-radius" id="change-orgname-btn" href="#change-orgname-modal">{{.i18n.Tr "org.settings.update_settings"}}</button> - </div> - </form> - </div> - </div> + <div id="org-setting" class="container clear"> + {{template "org/settings/nav" .}} + <div class="grid-4-5 left"> + <div class="setting-content"> + {{template "ng/base/alert" .}} + <div id="setting-content"> + <div id="user-profile-setting-content" class="panel panel-radius"> + <div class="panel-header"> + <strong>{{.i18n.Tr "org.settings.options"}}</strong> </div> - </div> - </div> + <form class="form form-align panel-body" id="org-setting-form" action="{{AppSubUrl}}/org/{{.Org.LowerName}}/settings" method="post"> + {{.CsrfTokenHtml}} + <input type="hidden" name="action" value="update"> + <div class="field"> + <label class="req" for="orgname">{{.i18n.Tr "username"}}</label> + <input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="orgname" name="uname" value="{{.Org.Name}}" data-orgname="{{.Org.Name}}" required /> + </div> + <div class="white-popup-block mfp-hide" id="change-orgname-modal"> + <h1 class="text-red">{{.i18n.Tr "org.settings.change_orgname"}}</h1> + <p>{{.i18n.Tr "org.settings.change_orgname_desc"}}</p> + <br> + <button class="btn btn-red btn-large btn-radius" id="change-orgname-submit">{{.i18n.Tr "settings.continue"}}</button> + <button class="btn btn-large btn-radius popup-modal-dismiss">{{.i18n.Tr "settings.cancel"}}</button> + </div> + <div class="field"> + <label for="full-name">{{.i18n.Tr "org.settings.full_name"}}</label> + <input class="ipt ipt-large ipt-radius {{if .Err_FullName}}ipt-error{{end}}" id="full-name" name="fullname" value="{{.Org.FullName}}" /> + </div> + <div class="field"> + <label class="req" for="email">{{.i18n.Tr "email"}}</label> + <input class="ipt ipt-large ipt-radius {{if .Err_Email}}ipt-error{{end}}" id="email" name="email" type="email" value="{{.Org.Email}}" required /> + </div> + <div class="field clear"> + <label class="left" for="desc">{{.i18n.Tr "org.org_desc"}}</label> + <textarea class="ipt ipt-large ipt-radius {{if .Err_Description}}ipt-error{{end}}" id="desc" name="desc">{{.Org.Description}}</textarea> + </div> + <div class="field"> + <label for="website">{{.i18n.Tr "org.settings.website"}}</label> + <input class="ipt ipt-large ipt-radius {{if .Err_Website}}ipt-error{{end}}" id="website" name="website" type="url" value="{{.Org.Website}}" /> + </div> + <div class="field"> + <label for="location">{{.i18n.Tr "org.settings.location"}}</label> + <input class="ipt ipt-large ipt-radius {{if .Err_Location}}ipt-error{{end}}" id="location" name="location" type="text" value="{{.Org.Location}}" /> + </div> + <div class="field"> + <label for="gravatar-email">Gravatar {{.i18n.Tr "email"}}</label> + <input class="ipt ipt-large ipt-radius {{if .Err_Avatar}}ipt-error{{end}}" id="gravatar-email" name="avatar" type="text" value="{{.Org.AvatarEmail}}" /> + </div> + <div class="field"> + <span class="form-label"></span> + <button class="btn btn-green btn-large btn-radius" id="change-orgname-btn" href="#change-orgname-modal">{{.i18n.Tr "org.settings.update_settings"}}</button> + </div> + </form> + </div> + </div> + </div> + </div> + </div> </div> {{template "ng/base/footer" .}}
\ No newline at end of file diff --git a/templates/repo/bare.tmpl b/templates/repo/bare.tmpl index 2a1409a6..c050b623 100644 --- a/templates/repo/bare.tmpl +++ b/templates/repo/bare.tmpl @@ -23,7 +23,7 @@ <h2>{{.i18n.Tr "repo.clone_this_repo"}}</h2> <button class="btn btn-blue current left btn-left-radius" id="repo-clone-ssh" data-link="{{.CloneLink.SSH}}">SSH</button> <button class="btn btn-gray left" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">HTTPS</button> - <input id="repo-clone-url" type="text" class="ipt ipt-disabled left" value="{{.CloneLink.SSH}}" readonly /> + <input id="repo-clone-url" type="text" class="ipt ipt-disabled left" value="{{.CloneLink.SSH}}" onclick="this.select()" readonly /> <button class="btn btn-black left btn-right-radius" id="repo-clone-copy" data-copy-val="val" data-copy-from="#repo-clone-url">{{.i18n.Tr "repo.copy_link"}}</button> <p class="text-center" id="repo-clone-help">{{.i18n.Tr "repo.clone_helper" | Str2html}}</p> <hr/> @@ -50,4 +50,4 @@ git push -u origin master</code></pre> </div> </div> </div> -{{template "ng/base/footer" .}}
\ No newline at end of file +{{template "ng/base/footer" .}} diff --git a/templates/repo/diff.tmpl b/templates/repo/diff.tmpl index 3d4a8b1f..f261da55 100644 --- a/templates/repo/diff.tmpl +++ b/templates/repo/diff.tmpl @@ -89,7 +89,11 @@ {{$.i18n.Tr "repo.diff.bin"}} {{end}} </div> + {{if $file.IsDeleted}} + <a class="btn btn-gray btn-header btn-radius text-black pull-right" rel="nofollow" href="{{$.BeforeSourcePath}}/{{.Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a> + {{else}} <a class="btn btn-gray btn-header btn-radius text-black pull-right" rel="nofollow" href="{{$.SourcePath}}/{{.Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a> + {{end}} <span class="file">{{$file.Name}}</span> </div> {{$isImage := (call $.IsImageFile $file.Name)}} @@ -101,14 +105,14 @@ {{else}} <table> <tbody> - {{range $j, $section := $file.Sections}} - {{range $k, $line := $section.Lines}} - <tr class="{{DiffLineTypeToStr .Type}}-code nl-{{$i}} ol-{{$i}}"> + {{range .Sections}} + {{range $k, $line := .Lines}} + <tr class="{{DiffLineTypeToStr .Type}}-code nl-{{$k}} ol-{{$k}}"> <td class="lines-num lines-num-old"> - <span rel="diff-{{Add $i 1}}L{{$j}}{{$k}}">{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}</span> + <span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}">{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}</span> </td> <td class="lines-num lines-num-new"> - <span rel="diff-{{Add $i 1}}L{{$j}}{{$k}}">{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}</span> + <span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}">{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}</span> </td> <td class="lines-code"> diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl index 9e52efc7..a0b927be 100644 --- a/templates/repo/header.tmpl +++ b/templates/repo/header.tmpl @@ -22,7 +22,7 @@ <button class="btn btn-blue left btn-left-radius" id="repo-clone-ssh" data-link="{{$.CloneLink.SSH}}">SSH</button> {{end}} <button class="btn {{if $.DisableSSH}}btn-blue{{else}}btn-gray{{end}} left" id="repo-clone-https" data-link="{{$.CloneLink.HTTPS}}">HTTPS</button> - <input id="repo-clone-url" class="ipt ipt-disabled left" value="{{if $.DisableSSH}}{{$.CloneLink.HTTPS}}{{else}}{{$.CloneLink.SSH}}{{end}}" readonly /> + <input id="repo-clone-url" class="ipt ipt-disabled left" value="{{if $.DisableSSH}}{{$.CloneLink.HTTPS}}{{else}}{{$.CloneLink.SSH}}{{end}}" onclick="this.select();" readonly /> <button id="repo-clone-copy" class="btn btn-black left btn-right-radius" data-copy-val="val" data-copy-from="#repo-clone-url" original-title="{{$.i18n.Tr "repo.click_to_copy"}}" data-original-title="{{$.i18n.Tr "repo.click_to_copy"}}" data-after-title="{{$.i18n.Tr "repo.copied"}}">{{$.i18n.Tr "repo.copy_link"}}</button> <p class="text-center" id="repo-clone-help">{{$.i18n.Tr "repo.clone_helper" "http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository" | Str2html}}</p> <hr/> @@ -60,4 +60,4 @@ </ul> </div> </div> -{{end}}
\ No newline at end of file +{{end}} diff --git a/templates/repo/migrate.tmpl b/templates/repo/migrate.tmpl index b28d0647..5869be15 100644 --- a/templates/repo/migrate.tmpl +++ b/templates/repo/migrate.tmpl @@ -7,8 +7,8 @@ <div class="panel-content"> {{template "ng/base/alert" .}} <div class="field"> - <label class="req" for="url">HTTPS URL</label> - <input class="ipt ipt-large ipt-radius {{if .Err_HttpsUrl}}ipt-error{{end}}" id="url" name="url" type="text" value="{{.url}}" required /> + <label class="req" for="clone_addr">{{.i18n.Tr "repo.migrate.clone_address"}}</label> + <input class="ipt ipt-large ipt-radius {{if .Err_CloneAddr}}ipt-error{{end}}" id="clone_addr" name="clone_addr" type="text" value="{{.clone_addr}}" required /> </div> <div class="field"> <span class="form-label"></span> diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index 093e9375..41683f84 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -59,11 +59,6 @@ <input class="ipt-chk" id="visibility" name="private" type="checkbox" {{if .Repository.IsPrivate}}checked{{end}} /> <span>{{.i18n.Tr "repo.visiblity_helper" | Str2html}}</span> </div> - <div class="field"> - <label for="goget">{{.i18n.Tr "repo.goget_meta"}}</label> - <input class="ipt-chk" id="goget" name="goget" type="checkbox" {{if .Repository.IsGoget}}checked{{end}} /> - <span>{{.i18n.Tr "repo.goget_meta_helper" | Str2html}}</span> - </div> <div class="field"> <span class="form-label"></span> <button class="btn btn-green btn-large btn-radius" id="change-reponame-btn" href="#change-reponame-modal">{{.i18n.Tr "repo.settings.update_settings"}}</button> diff --git a/templates/user/auth/signin.tmpl b/templates/user/auth/signin.tmpl index 78d6febb..455df63a 100644 --- a/templates/user/auth/signin.tmpl +++ b/templates/user/auth/signin.tmpl @@ -26,10 +26,12 @@ <button class="btn btn-green btn-large btn-radius">{{.i18n.Tr "sign_in"}}</button> {{if not .IsSocialLogin}}<a href="{{AppSubUrl}}/user/forget_password">{{.i18n.Tr "auth.forget_password"}}</a>{{end}} </div> + {{if .ShowRegistrationButton}} <div class="field"> <label></label> <a href="{{AppSubUrl}}/user/sign_up">{{.i18n.Tr "auth.sign_up_now" | Str2html}}</a> </div> + {{end}} {{if and (not .IsSocialLogin) .OauthEnabled}} <hr/> <div id="sign-social" class="text-center social-buttons"> diff --git a/templates/user/dashboard/feeds.tmpl b/templates/user/dashboard/feeds.tmpl index 834e5f0a..8acf2289 100644 --- a/templates/user/dashboard/feeds.tmpl +++ b/templates/user/dashboard/feeds.tmpl @@ -12,14 +12,14 @@ {{$.i18n.Tr "action.commit_repo" AppSubUrl .GetRepoLink .GetBranch .GetBranch AppSubUrl .GetRepoLink .GetRepoLink | Str2html}} {{else if eq .GetOpType 6}} {{ $index := index .GetIssueInfos 0}} - {{$.i18n.Tr "action.create_issue" AppSubUrl .GetRepoLink $index .GetRepoLink $index | Str2html}} + {{$.i18n.Tr "action.create_issue" .GetRepoLink $index | Str2html}} {{else if eq .GetOpType 8}} {{$.i18n.Tr "action.transfer_repo" .GetContent AppSubUrl .GetRepoLink .GetRepoLink | Str2html}} {{else if eq .GetOpType 9}} {{$.i18n.Tr "action.push_tag" AppSubUrl .GetRepoLink .GetBranch .GetBranch AppSubUrl .GetRepoLink .GetRepoLink | Str2html}} {{else if eq .GetOpType 10}} {{ $index := index .GetIssueInfos 0}} - {{$.i18n.Tr "action.comment_issue" AppSubUrl .GetRepoLink $index .GetRepoLink $index | Str2html}} + {{$.i18n.Tr "action.comment_issue" .GetRepoLink $index | Str2html}} {{end}} </p> {{if eq .GetOpType 5}} diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index 44c22123..a18a8b50 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -28,7 +28,7 @@ {{if .Owner.Website}} <li class="list-group-item"><i class="octicon octicon-link"></i> <a target="_blank" href="{{.Owner.Website}}">{{.Owner.Website}}</a></li> {{end}} - <li class="list-group-item"><i class="octicon octicon-clock"></i> {{.i18n.Tr "user.join_on"}} {{DateFormat .Owner.Created "M d, Y"}}</li> + <li class="list-group-item"><i class="octicon octicon-clock"></i> {{.i18n.Tr "user.join_on"}} {{DateFmtShort .Owner.Created}}</li> </ul> <hr> <ul class="list-no-style"> diff --git a/templates/user/settings/applications.tmpl b/templates/user/settings/applications.tmpl index ce74ef77..2e766a3d 100644 --- a/templates/user/settings/applications.tmpl +++ b/templates/user/settings/applications.tmpl @@ -22,7 +22,7 @@ <i class="fa fa-send fa-2x left"></i> <div class="ssh-content left"> <p><strong>{{.Name}}</strong></p> - <p class="activity"><i>{{$.i18n.Tr "settings.add_on"}} <span title="{{DateFormat .Created "r"}}">{{DateFormat .Created "M d, Y"}}</span> — <i class="octicon octicon-info"></i>{{if .HasUsed}}{{$.i18n.Tr "settings.last_used"}} {{DateFormat .Updated "M d, Y"}}{{else}}{{$.i18n.Tr "settings.no_activity"}}{{end}}</i></p> + <p class="activity"><i>{{$.i18n.Tr "settings.add_on"}} <span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created}}</span> — <i class="octicon octicon-info"></i>{{if .HasUsed}}{{$.i18n.Tr "settings.last_used"}} {{DateFmtShort .Updated}}{{else}}{{$.i18n.Tr "settings.no_activity"}}{{end}}</i></p> </div> <a href="{{AppSubUrl}}/user/settings/applications?remove={{.Id}}"> <button class="btn btn-small btn-red btn-radius ssh-btn right">{{$.i18n.Tr "settings.delete_token"}}</button> diff --git a/templates/user/settings/email.tmpl b/templates/user/settings/email.tmpl index c99e6a04..ec152c5d 100644 --- a/templates/user/settings/email.tmpl +++ b/templates/user/settings/email.tmpl @@ -16,7 +16,7 @@ {{range .Emails}} <li class="email clear"> <div class="email-content left"> - <p><strong>{{.Email}}</strong> {{if .IsPrimary}} <span class="email-primary">{{$.i18n.Tr "settings.primary"}}</span> {{end}}</p> + <p><strong>{{.Email}}</strong> {{if .IsPrimary}} <span class="text-red">{{$.i18n.Tr "settings.primary"}}</span> {{end}}</p> </div> {{if not .IsPrimary}} {{if .IsActivated}} @@ -24,14 +24,14 @@ {{$.CsrfTokenHtml}} <input name="_method" type="hidden" value="PRIMARY"> <input name="id" type="hidden" value="{{.Id}}"> - <button class="right email-btn btn btn-green btn-radius btn-small">{{$.i18n.Tr "settings.primary_email"}}</button> + <button class="right email-btn btn btn-small btn-green btn-radius">{{$.i18n.Tr "settings.primary_email"}}</button> </form> {{end}} <form action="{{AppSubUrl}}/user/settings/email" method="post"> {{$.CsrfTokenHtml}} <input name="_method" type="hidden" value="DELETE"> <input name="id" type="hidden" value="{{.Id}}"> - <button class="right email-btn btn btn-red btn-radius btn-small">{{$.i18n.Tr "settings.delete_email"}}</button> + <button class="right email-btn btn btn-small btn-red btn-radius" style="margin-right: 5px">{{$.i18n.Tr "settings.delete_email"}}</button> </form> {{end}} </li> diff --git a/templates/user/settings/social.tmpl b/templates/user/settings/social.tmpl index b47f883e..f2a30da7 100644 --- a/templates/user/settings/social.tmpl +++ b/templates/user/settings/social.tmpl @@ -18,7 +18,7 @@ <div class="ssh-content left"> <p><strong>{{Oauth2Name .Type}}</strong></p> <p class="print">{{.Identity}}</p> - <p class="activity"><i>{{$.i18n.Tr "settings.add_on"}} <span title="{{DateFormat .Created "r"}}">{{DateFormat .Created "M d, Y"}}</span> — <i class="octicon octicon-info"></i>{{$.i18n.Tr "settings.last_used"}} {{DateFormat .Updated "M d, Y"}}</i></p> + <p class="activity"><i>{{$.i18n.Tr "settings.add_on"}} <span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created}}</span> — <i class="octicon octicon-info"></i>{{$.i18n.Tr "settings.last_used"}} {{DateFmtShort .Updated}}</i></p> </div> <a class="right btn btn-small btn-red btn-header btn-radius" href="{{AppSubUrl}}/user/settings/social?remove={{.Id}}">{{$.i18n.Tr "settings.unbind"}}</a> </li> diff --git a/templates/user/settings/sshkeys.tmpl b/templates/user/settings/sshkeys.tmpl index 48a4d343..42b76039 100644 --- a/templates/user/settings/sshkeys.tmpl +++ b/templates/user/settings/sshkeys.tmpl @@ -23,7 +23,7 @@ <div class="ssh-content left"> <p><strong>{{.Name}}</strong></p> <p class="print">{{.Fingerprint}}</p> - <p class="activity"><i>{{$.i18n.Tr "settings.add_on"}} <span title="{{DateFormat .Created "r"}}">{{DateFormat .Created "M d, Y"}}</span> — <i class="octicon octicon-info"></i>{{if .HasUsed}}{{$.i18n.Tr "settings.last_used"}} <span title="{{DateFormat .Updated "r"}}">{{DateFormat .Updated "M d, Y"}}</span>{{else}}{{$.i18n.Tr "settings.no_activity"}}{{end}}</i></p> + <p class="activity"><i>{{$.i18n.Tr "settings.add_on"}} <span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created}}</span> — <i class="octicon octicon-info"></i>{{if .HasUsed}}{{$.i18n.Tr "settings.last_used"}} <span title="{{DateFmtLong .Updated}}">{{DateFmtShort .Updated}}</span>{{else}}{{$.i18n.Tr "settings.no_activity"}}{{end}}</i></p> </div> <form action="{{AppSubUrl}}/user/settings/ssh" method="post"> {{$.CsrfTokenHtml}} |