summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Smit <peter@smitmail.eu>2015-02-23 12:34:41 +0200
committerPeter Smit <peter@smitmail.eu>2015-02-23 12:34:41 +0200
commit556881964fb8137561e9f381d4a5aaef97627cc5 (patch)
tree32aebddd8c123c540cf04ac6dfd0e503450d9247
parentaa68e86206d7d9fc74de8630acfa07dfd7f1bc95 (diff)
parentee68a826a55c6a4305e7f609db57501a54a5bc47 (diff)
downloadgitea-556881964fb8137561e9f381d4a5aaef97627cc5.tar.gz
gitea-556881964fb8137561e9f381d4a5aaef97627cc5.zip
Merge branch 'access' into access_rewriteserv
-rw-r--r--.gopmfile41
-rw-r--r--.travis.yml3
-rw-r--r--CONTRIBUTING.md20
-rw-r--r--README.md30
-rw-r--r--cmd/web.go11
-rwxr-xr-xconf/locale/locale_de-DE.ini1
-rw-r--r--conf/locale/locale_en-US.ini4
-rwxr-xr-xconf/locale/locale_es-ES.ini1
-rwxr-xr-xconf/locale/locale_fr-CA.ini15
-rwxr-xr-xconf/locale/locale_ja-JP.ini1
-rwxr-xr-xconf/locale/locale_lv-LV.ini1
-rwxr-xr-xconf/locale/locale_nl-NL.ini5
-rwxr-xr-xconf/locale/locale_ru-RU.ini19
-rwxr-xr-xconf/locale/locale_zh-CN.ini1
-rwxr-xr-xconf/locale/locale_zh-HK.ini1
-rw-r--r--docker/blocks/docker_gogs/Dockerfile2
-rw-r--r--docker/blocks/docker_gogs_dev/Dockerfile2
-rw-r--r--docker/templates/init_gogs.sh.tpl2
-rw-r--r--gogs.go2
-rw-r--r--models/access.go37
-rw-r--r--models/action.go20
-rw-r--r--models/issue.go2
-rw-r--r--models/migrations/migrations.go76
-rw-r--r--models/models.go5
-rw-r--r--models/org.go298
-rw-r--r--models/repo.go144
-rw-r--r--models/user.go23
-rw-r--r--modules/auth/repo_form.go3
-rw-r--r--modules/auth/user_form.go2
-rw-r--r--modules/base/template.go14
-rw-r--r--modules/base/tool.go67
-rw-r--r--modules/git/signature.go29
-rw-r--r--modules/mailer/mailer.go10
-rw-r--r--modules/middleware/context.go67
-rw-r--r--modules/middleware/repo.go50
-rw-r--r--modules/setting/setting.go10
-rw-r--r--public/ng/css/gogs.css4
-rw-r--r--public/ng/js/gogs.js37
-rw-r--r--public/ng/less/gogs/repository.less4
-rw-r--r--routers/api/v1/repo.go75
-rw-r--r--routers/api/v1/repo_file.go2
-rw-r--r--routers/install.go6
-rw-r--r--routers/org/setting.go15
-rw-r--r--routers/org/teams.go2
-rw-r--r--routers/repo/http.go5
-rw-r--r--routers/repo/issue.go14
-rw-r--r--routers/repo/release.go10
-rw-r--r--routers/repo/repo.go30
-rw-r--r--routers/repo/setting.go3
-rw-r--r--routers/user/auth.go5
-rw-r--r--routers/user/setting.go91
-rwxr-xr-xscripts/less.sh5
-rw-r--r--templates/.VERSION2
-rw-r--r--templates/admin/auth/list.tmpl4
-rw-r--r--templates/admin/org/list.tmpl2
-rw-r--r--templates/admin/repo/list.tmpl2
-rw-r--r--templates/admin/user/list.tmpl2
-rw-r--r--templates/base/head.tmpl2
-rw-r--r--templates/ng/base/head.tmpl2
-rw-r--r--templates/org/base/header.tmpl2
-rw-r--r--templates/org/home.tmpl140
-rw-r--r--templates/org/settings/nav.tmpl20
-rw-r--r--templates/org/settings/options.tmpl114
-rw-r--r--templates/repo/bare.tmpl4
-rw-r--r--templates/repo/diff.tmpl10
-rw-r--r--templates/repo/header.tmpl2
-rw-r--r--templates/repo/migrate.tmpl4
-rw-r--r--templates/repo/settings/options.tmpl5
-rw-r--r--templates/repo/sidebar.tmpl2
-rw-r--r--templates/repo/toolbar.tmpl2
-rw-r--r--templates/user/auth/signin.tmpl2
-rw-r--r--templates/user/profile.tmpl2
-rw-r--r--templates/user/settings/applications.tmpl2
-rw-r--r--templates/user/settings/email.tmpl6
-rw-r--r--templates/user/settings/social.tmpl2
-rw-r--r--templates/user/settings/sshkeys.tmpl2
76 files changed, 902 insertions, 762 deletions
diff --git a/.gopmfile b/.gopmfile
index d09e632bd7..e28fe0d3c0 100644
--- a/.gopmfile
+++ b/.gopmfile
@@ -2,35 +2,34 @@
path = github.com/gogits/gogs
[deps]
-github.com/beego/memcache = commit:2aea774416
-github.com/bradfitz/gomemcache =
+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
+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:28ad8c408b
+gopkg.in/ini.v1 = commit:4febc4104c
gopkg.in/redis.v2 = commit:e617904962
[res]
diff --git a/.travis.yml b/.travis.yml
index 85e5f396ea..4149e17316 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 d3619018a4..411a8e9319 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
diff --git a/README.md b/README.md
index a601bb773b..150aa64de8 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@ Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?bra
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gogits/gogs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-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.
![Demo](http://gogs.qiniudn.com/gogs_demo.gif)
@@ -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/unknwon/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([10 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/cmd/web.go b/cmd/web.go
index 3284acb9df..8213baab2c 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -79,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"},
@@ -166,12 +166,11 @@ func newMacaron() *macaron.Macaron {
}
func runWeb(ctx *cli.Context) {
- checkVersion()
-
if ctx.IsSet("config") {
setting.CustomConf = ctx.String("config")
}
routers.GlobalInit()
+ checkVersion()
m := newMacaron()
@@ -230,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")
})
})
})
@@ -319,7 +318,7 @@ func runWeb(ctx *cli.Context) {
m.Get("/template/*", dev.TemplatePreview)
}
- reqTrueOwner := middleware.RequireTrueOwner()
+ reqAdmin := middleware.RequireAdmin()
// Organization.
m.Group("/org", func() {
@@ -394,7 +393,7 @@ func runWeb(ctx *cli.Context) {
m.Post("/:name", repo.GitHooksEditPost)
}, middleware.GitHookService())
})
- }, reqSignIn, middleware.RepoAssignment(true), reqTrueOwner)
+ }, reqSignIn, middleware.RepoAssignment(true), reqAdmin)
m.Group("/:username/:reponame", func() {
m.Get("/action/:action", repo.Action)
diff --git a/conf/locale/locale_de-DE.ini b/conf/locale/locale_de-DE.ini
index 1dc7523b0f..31ee931b9e 100755
--- a/conf/locale/locale_de-DE.ini
+++ b/conf/locale/locale_de-DE.ini
@@ -647,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
diff --git a/conf/locale/locale_en-US.ini b/conf/locale/locale_en-US.ini
index 6b59be7391..ca076b8bb4 100644
--- a/conf/locale/locale_en-US.ini
+++ b/conf/locale/locale_en-US.ini
@@ -281,13 +281,13 @@ 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>
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
diff --git a/conf/locale/locale_es-ES.ini b/conf/locale/locale_es-ES.ini
index d7fab5f961..046bab8969 100755
--- a/conf/locale/locale_es-ES.ini
+++ b/conf/locale/locale_es-ES.ini
@@ -647,6 +647,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
diff --git a/conf/locale/locale_fr-CA.ini b/conf/locale/locale_fr-CA.ini
index 94a2e96867..e744b9d97c 100755
--- a/conf/locale/locale_fr-CA.ini
+++ b/conf/locale/locale_fr-CA.ini
@@ -59,8 +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=HTTP Port
-http_port_helper=Port number which application will listen on.
+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)
@@ -514,10 +514,10 @@ 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=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.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
@@ -638,7 +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=Show Register Button
+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
@@ -647,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
diff --git a/conf/locale/locale_ja-JP.ini b/conf/locale/locale_ja-JP.ini
index 29ea94e4da..441da8feb8 100755
--- a/conf/locale/locale_ja-JP.ini
+++ b/conf/locale/locale_ja-JP.ini
@@ -647,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=名前
diff --git a/conf/locale/locale_lv-LV.ini b/conf/locale/locale_lv-LV.ini
index 6ab814806f..b640972c81 100755
--- a/conf/locale/locale_lv-LV.ini
+++ b/conf/locale/locale_lv-LV.ini
@@ -647,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
diff --git a/conf/locale/locale_nl-NL.ini b/conf/locale/locale_nl-NL.ini
index adc98c9d5a..0a4ecb43a7 100755
--- a/conf/locale/locale_nl-NL.ini
+++ b/conf/locale/locale_nl-NL.ini
@@ -516,8 +516,8 @@ 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=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.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
@@ -647,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
diff --git a/conf/locale/locale_ru-RU.ini b/conf/locale/locale_ru-RU.ini
index aa2c0ee558..e21dca14df 100755
--- a/conf/locale/locale_ru-RU.ini
+++ b/conf/locale/locale_ru-RU.ini
@@ -58,11 +58,11 @@ repo_path_helper=Всех удаленные репозитории Git буде
run_user=Пользователь
run_user_helper=У пользователя должен быть доступ к пути к корню репозитория и к запуску Gogs.
domain=Домен
-domain_helper=This affects SSH clone URLs.
-http_port=HTTP Port
-http_port_helper=Port number which application will listen on.
+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=Электронная почта отправителя
@@ -80,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. Веселитесь и берегите себя.
@@ -88,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=Моя Организация
@@ -280,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=Тип миграции
@@ -647,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=Имя
diff --git a/conf/locale/locale_zh-CN.ini b/conf/locale/locale_zh-CN.ini
index efeca15adb..3537068228 100755
--- a/conf/locale/locale_zh-CN.ini
+++ b/conf/locale/locale_zh-CN.ini
@@ -647,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=发送者名称
diff --git a/conf/locale/locale_zh-HK.ini b/conf/locale/locale_zh-HK.ini
index 0c9ba19091..a9b51a5b0c 100755
--- a/conf/locale/locale_zh-HK.ini
+++ b/conf/locale/locale_zh-HK.ini
@@ -647,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=發送者名稱
diff --git a/docker/blocks/docker_gogs/Dockerfile b/docker/blocks/docker_gogs/Dockerfile
index 2c98cc5011..efedc31a80 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 2a628c2d5e..ce653fbe7e 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 26cff4e501..ada11f95ae 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 "
diff --git a/gogs.go b/gogs.go
index 247bfbfbb4..58cbb1a05c 100644
--- a/gogs.go
+++ b/gogs.go
@@ -17,7 +17,7 @@ import (
"github.com/gogits/gogs/modules/setting"
)
-const APP_VER = "0.5.14.0213 Beta"
+const APP_VER = "0.5.15.0223 Beta"
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
diff --git a/models/access.go b/models/access.go
index 1e1c0114ed..29d1a730b7 100644
--- a/models/access.go
+++ b/models/access.go
@@ -24,21 +24,19 @@ type Access struct {
Mode AccessMode
}
-// Return the Access a user has to a repository. Will return NoneAccess if the
-// user does not have access. User can be nil!
-func AccessLevel(u *User, r *Repository) (AccessMode, error) {
+func accessLevel(e Engine, u *User, repo *Repository) (AccessMode, error) {
mode := ACCESS_MODE_NONE
- if !r.IsPrivate {
+ if !repo.IsPrivate {
mode = ACCESS_MODE_READ
}
if u != nil {
- if u.Id == r.OwnerId {
+ if u.Id == repo.OwnerId {
return ACCESS_MODE_OWNER, nil
}
- a := &Access{UserID: u.Id, RepoID: r.Id}
- if has, err := x.Get(a); !has || err != nil {
+ a := &Access{UserID: u.Id, RepoID: repo.Id}
+ if has, err := e.Get(a); !has || err != nil {
return mode, err
}
return a.Mode, nil
@@ -47,12 +45,22 @@ func AccessLevel(u *User, r *Repository) (AccessMode, error) {
return mode, nil
}
-// HasAccess returns true if someone has the request access level. User can be nil!
-func HasAccess(u *User, r *Repository, testMode AccessMode) (bool, error) {
- mode, err := AccessLevel(u, r)
+// AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the
+// user does not have access. User can be nil!
+func AccessLevel(u *User, repo *Repository) (AccessMode, error) {
+ return accessLevel(x, u, repo)
+}
+
+func hasAccess(e Engine, u *User, repo *Repository, testMode AccessMode) (bool, error) {
+ mode, err := accessLevel(e, u, repo)
return testMode <= mode, err
}
+// HasAccess returns true if someone has the request access level. User can be nil!
+func HasAccess(u *User, repo *Repository, testMode AccessMode) (bool, error) {
+ return hasAccess(x, u, repo, testMode)
+}
+
// GetAccessibleRepositories finds all repositories where a user has access to,
// besides his own.
func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) {
@@ -96,7 +104,8 @@ func (repo *Repository) recalculateTeamAccesses(e Engine, mode AccessMode) error
func (repo *Repository) recalculateAccesses(e Engine) error {
accessMap := make(map[int64]AccessMode, 20)
- // Give all collaborators write access
+ // FIXME: should be able to have read-only access.
+ // Give all collaborators write access.
collaborators, err := repo.getCollaborators(e)
if err != nil {
return err
@@ -114,9 +123,7 @@ func (repo *Repository) recalculateAccesses(e Engine) error {
}
for _, team := range repo.Owner.Teams {
- if !(team.IsOwnerTeam() || team.HasRepository(repo)) {
- continue
- } else if team.IsOwnerTeam() {
+ if team.IsOwnerTeam() {
team.Authorize = ACCESS_MODE_OWNER
}
@@ -129,6 +136,8 @@ func (repo *Repository) recalculateAccesses(e Engine) error {
}
}
+ // FIXME: do corss-comparison so reduce deletions and additions to the minimum?
+
minMode := ACCESS_MODE_READ
if !repo.IsPrivate {
minMode = ACCESS_MODE_WRITE
diff --git a/models/action.go b/models/action.go
index 9ba661f1e2..fee5e5e676 100644
--- a/models/action.go
+++ b/models/action.go
@@ -434,20 +434,20 @@ func NewRepoAction(u *User, repo *Repository) (err error) {
return newRepoAction(x, u, repo)
}
-func transferRepoAction(e Engine, u, newUser *User, repo *Repository) (err error) {
+func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repository) (err error) {
action := &Action{
- ActUserId: u.Id,
- ActUserName: u.Name,
- ActEmail: u.Email,
+ ActUserId: actUser.Id,
+ ActUserName: actUser.Name,
+ ActEmail: actUser.Email,
OpType: TRANSFER_REPO,
RepoId: repo.Id,
- RepoUserName: newUser.Name,
+ RepoUserName: newOwner.Name,
RepoName: repo.Name,
IsPrivate: repo.IsPrivate,
- Content: path.Join(repo.Owner.LowerName, repo.LowerName),
+ Content: path.Join(oldOwner.LowerName, repo.LowerName),
}
if err = notifyWatchers(e, action); err != nil {
- return fmt.Errorf("notify watchers '%d/%s'", u.Id, repo.Id)
+ return fmt.Errorf("notify watchers '%d/%s'", actUser.Id, repo.Id)
}
// Remove watch for organization.
@@ -457,13 +457,13 @@ func transferRepoAction(e Engine, u, newUser *User, repo *Repository) (err error
}
}
- log.Trace("action.TransferRepoAction: %s/%s", u.Name, repo.Name)
+ log.Trace("action.TransferRepoAction: %s/%s", actUser.Name, repo.Name)
return nil
}
// TransferRepoAction adds new action for transferring repository.
-func TransferRepoAction(u, newUser *User, repo *Repository) (err error) {
- return transferRepoAction(x, u, newUser, repo)
+func TransferRepoAction(actUser, oldOwner, newOwner *User, repo *Repository) (err error) {
+ return transferRepoAction(x, actUser, oldOwner, newOwner, repo)
}
// GetFeeds returns action list of given user in given context.
diff --git a/models/issue.go b/models/issue.go
index 3cd71d8aa4..2b80e57608 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -564,7 +564,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/migrations/migrations.go b/models/migrations/migrations.go
index f6ef513207..25c130a926 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -53,6 +53,7 @@ var migrations = []Migration{
NewMigration("generate collaboration from access", accessToCollaboration), // V0 -> V1
NewMigration("make authorize 4 if team is owners", ownerTeamUpdate), // V1 -> V2
NewMigration("refactor access table to use id's", accessRefactor), // V2 -> V3
+ NewMigration("generate team-repo from team", teamToTeamRepo), // V3 -> V4
}
// Migrate database to current version
@@ -214,8 +215,8 @@ func accessToCollaboration(x *xorm.Engine) (err error) {
}
func ownerTeamUpdate(x *xorm.Engine) (err error) {
- if _, err := x.Exec("UPDATE team SET authorize=4 WHERE lower_name=?", "owners"); err != nil {
- return fmt.Errorf("drop table: %v", err)
+ if _, err := x.Exec("UPDATE `team` SET authorize=4 WHERE lower_name=?", "owners"); err != nil {
+ return fmt.Errorf("update owner team table: %v", err)
}
return nil
}
@@ -239,9 +240,9 @@ func accessRefactor(x *xorm.Engine) (err error) {
accessMap := make(map[UserRepo]AccessMode, 50)
- results, err := x.Query("SELECT r.id as `repo_id`, r.is_private as `is_private`, r.owner_id as `owner_id`, u.type as `owner_type` FROM `repository` r LEFT JOIN user u ON r.owner_id=u.id")
+ results, err := x.Query("SELECT r.id AS `repo_id`, r.is_private AS `is_private`, r.owner_id AS `owner_id`, u.type AS `owner_type` FROM `repository` r LEFT JOIN `user` u ON r.owner_id=u.id")
if err != nil {
- return err
+ return fmt.Errorf("select repositories: %v", err)
}
for _, repo := range results {
repoID := com.StrTo(repo["repo_id"]).MustInt64()
@@ -249,9 +250,9 @@ func accessRefactor(x *xorm.Engine) (err error) {
ownerID := com.StrTo(repo["owner_id"]).MustInt64()
ownerIsOrganization := com.StrTo(repo["owner_type"]).MustInt() > 0
- results, err := x.Query("SELECT user_id FROM collaboration WHERE repo_id=?", repoID)
+ results, err := x.Query("SELECT `user_id` FROM `collaboration` WHERE repo_id=?", repoID)
if err != nil {
- return fmt.Errorf("select repos: %v", err)
+ return fmt.Errorf("select collaborators: %v", err)
}
for _, user := range results {
userID := com.StrTo(user["user_id"]).MustInt64()
@@ -262,6 +263,8 @@ func accessRefactor(x *xorm.Engine) (err error) {
continue
}
+ // The minimum level to add a new access record,
+ // because public repository has implicit open access.
minAccessLevel := AccessMode(0)
if !isPrivate {
minAccessLevel = 1
@@ -269,7 +272,7 @@ func accessRefactor(x *xorm.Engine) (err error) {
repoString := "$" + string(repo["repo_id"]) + "|"
- results, err = x.Query("SELECT id, authorize, repo_ids FROM team WHERE org_id=? AND authorize > ? ORDER BY authorize ASC", ownerID, int(minAccessLevel))
+ results, err = x.Query("SELECT `id`,`authorize`,`repo_ids` FROM `team` WHERE org_id=? AND authorize>? ORDER BY `authorize` ASC", ownerID, int(minAccessLevel))
if err != nil {
return fmt.Errorf("select teams from org: %v", err)
}
@@ -281,20 +284,20 @@ func accessRefactor(x *xorm.Engine) (err error) {
teamID := com.StrTo(team["id"]).MustInt64()
mode := AccessMode(com.StrTo(team["authorize"]).MustInt())
- results, err := x.Query("SELECT uid FROM team_user WHERE team_id=?", teamID)
+ results, err := x.Query("SELECT `uid` FROM `team_user` WHERE team_id=?", teamID)
if err != nil {
return fmt.Errorf("select users from team: %v", err)
}
for _, user := range results {
- userID := com.StrTo(user["uid"]).MustInt64()
+ userID := com.StrTo(user["user_id"]).MustInt64()
accessMap[UserRepo{userID, repoID}] = mode
}
}
}
// Drop table can't be in a session (at least not in sqlite)
- if _, err = x.Exec("DROP TABLE access"); err != nil {
- return fmt.Errorf("drop table: %v", err)
+ if _, err = x.Exec("DROP TABLE `access`"); err != nil {
+ return fmt.Errorf("drop access table: %v", err)
}
// Now we start writing so we make a session
@@ -313,7 +316,56 @@ func accessRefactor(x *xorm.Engine) (err error) {
accesses = append(accesses, &Access{UserID: ur.UserID, RepoID: ur.RepoID, Mode: mode})
}
- _, err = sess.Insert(accesses)
+ if _, err = sess.Insert(accesses); err != nil {
+ return fmt.Errorf("insert accesses: %v", err)
+ }
+
+ return sess.Commit()
+}
+
+func teamToTeamRepo(x *xorm.Engine) error {
+ type TeamRepo struct {
+ ID int64 `xorm:"pk autoincr"`
+ OrgID int64 `xorm:"INDEX"`
+ TeamID int64 `xorm:"UNIQUE(s)"`
+ RepoID int64 `xorm:"UNIQUE(s)"`
+ }
+
+ teamRepos := make([]*TeamRepo, 0, 50)
+
+ results, err := x.Query("SELECT `id`,`org_id`,`repo_ids` FROM `team`")
+ if err != nil {
+ return fmt.Errorf("select teams: %v", err)
+ }
+ for _, team := range results {
+ orgID := com.StrTo(team["org_id"]).MustInt64()
+ teamID := com.StrTo(team["id"]).MustInt64()
+
+ for _, idStr := range strings.Split(string(team["repo_ids"]), "|") {
+ repoID := com.StrTo(strings.TrimPrefix(idStr, "$")).MustInt64()
+ if repoID == 0 {
+ continue
+ }
+
+ teamRepos = append(teamRepos, &TeamRepo{
+ OrgID: orgID,
+ TeamID: teamID,
+ RepoID: repoID,
+ })
+ }
+ }
+
+ sess := x.NewSession()
+ defer sessionRelease(sess)
+ if err = sess.Begin(); err != nil {
+ return err
+ }
+
+ if err = sess.Sync2(new(TeamRepo)); err != nil {
+ return fmt.Errorf("sync: %v", err)
+ } else if _, err = sess.Insert(teamRepos); err != nil {
+ return fmt.Errorf("insert team-repos: %v", err)
+ }
return sess.Commit()
}
diff --git a/models/models.go b/models/models.go
index 1cb7229645..a9436fca85 100644
--- a/models/models.go
+++ b/models/models.go
@@ -59,7 +59,8 @@ func init() {
new(Watch), new(Star), new(Follow), new(Action),
new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone),
new(Mirror), new(Release), new(LoginSource), new(Webhook),
- new(UpdateTask), new(HookTask), new(Team), new(OrgUser), new(TeamUser),
+ new(UpdateTask), new(HookTask),
+ new(Team), new(OrgUser), new(TeamUser), new(TeamRepo),
new(Notice), new(EmailAddress))
}
@@ -140,7 +141,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
diff --git a/models/org.go b/models/org.go
index 115a062b4e..629e9345c3 100644
--- a/models/org.go
+++ b/models/org.go
@@ -6,11 +6,10 @@ package models
import (
"errors"
+ "fmt"
"os"
"strings"
- "github.com/Unknwon/com"
-
"github.com/gogits/gogs/modules/base"
)
@@ -103,7 +102,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 {
@@ -126,53 +125,48 @@ func CreateOrganization(org, owner *User) (*User, error) {
org.NumMembers = 1
sess := x.NewSession()
- defer sess.Close()
+ defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return nil, err
}
if _, err = sess.Insert(org); err != nil {
- sess.Rollback()
- return nil, err
- }
-
- if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil {
- sess.Rollback()
return nil, err
}
// Create default owner team.
t := &Team{
- OrgId: org.Id,
+ OrgID: org.Id,
LowerName: strings.ToLower(OWNER_TEAM),
Name: OWNER_TEAM,
Authorize: ACCESS_MODE_OWNER,
NumMembers: 1,
}
if _, err = sess.Insert(t); err != nil {
- sess.Rollback()
return nil, err
}
// Add initial creator to organization and owner team.
ou := &OrgUser{
Uid: owner.Id,
- OrgId: org.Id,
+ OrgID: org.Id,
IsOwner: true,
NumTeams: 1,
}
if _, err = sess.Insert(ou); err != nil {
- sess.Rollback()
return nil, err
}
tu := &TeamUser{
Uid: owner.Id,
- OrgId: org.Id,
- TeamId: t.Id,
+ OrgID: org.Id,
+ TeamID: t.ID,
}
if _, err = sess.Insert(tu); err != nil {
- sess.Rollback()
+ return nil, err
+ }
+
+ if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil {
return nil, err
}
@@ -223,15 +217,15 @@ func DeleteOrganization(org *User) (err error) {
return err
}
- if _, err = sess.Delete(&Team{OrgId: org.Id}); err != nil {
+ if _, err = sess.Delete(&Team{OrgID: org.Id}); err != nil {
sess.Rollback()
return err
}
- if _, err = sess.Delete(&OrgUser{OrgId: org.Id}); err != nil {
+ if _, err = sess.Delete(&OrgUser{OrgID: org.Id}); err != nil {
sess.Rollback()
return err
}
- if _, err = sess.Delete(&TeamUser{OrgId: org.Id}); err != nil {
+ if _, err = sess.Delete(&TeamUser{OrgID: org.Id}); err != nil {
sess.Rollback()
return err
}
@@ -247,9 +241,9 @@ func DeleteOrganization(org *User) (err error) {
// OrgUser represents an organization-user relation.
type OrgUser struct {
- Id int64
+ ID int64 `xorm:"pk autoincr"`
Uid int64 `xorm:"INDEX UNIQUE(s)"`
- OrgId int64 `xorm:"INDEX UNIQUE(s)"`
+ OrgID int64 `xorm:"INDEX UNIQUE(s)"`
IsPublic bool
IsOwner bool
NumTeams int
@@ -298,7 +292,7 @@ func ChangeOrgUserStatus(orgId, uid int64, public bool) error {
}
ou.IsPublic = public
- _, err = x.Id(ou.Id).AllCols().Update(ou)
+ _, err = x.Id(ou.ID).AllCols().Update(ou)
return err
}
@@ -316,7 +310,7 @@ func AddOrgUser(orgId, uid int64) error {
ou := &OrgUser{
Uid: uid,
- OrgId: orgId,
+ OrgID: orgId,
}
if _, err := sess.Insert(ou); err != nil {
@@ -367,7 +361,7 @@ func RemoveOrgUser(orgId, uid int64) error {
return err
}
- if _, err := sess.Id(ou.Id).Delete(ou); err != nil {
+ if _, err := sess.Id(ou.ID).Delete(ou); err != nil {
sess.Rollback()
return err
} else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members - 1 WHERE id = ?", orgId); err != nil {
@@ -400,7 +394,7 @@ func RemoveOrgUser(orgId, uid int64) error {
return err
}
for _, t := range ts {
- if err = removeTeamMember(sess, org.Id, t.Id, u.Id); err != nil {
+ if err = removeTeamMember(sess, org.Id, t.ID, u.Id); err != nil {
return err
}
}
@@ -419,13 +413,12 @@ const OWNER_TEAM = "Owners"
// Team represents a organization team.
type Team struct {
- Id int64
- OrgId int64 `xorm:"INDEX"`
+ ID int64 `xorm:"pk autoincr"`
+ OrgID int64 `xorm:"INDEX"`
LowerName string
Name string
Description string
Authorize AccessMode
- RepoIds string `xorm:"TEXT"`
Repos []*Repository `xorm:"-"`
Members []*User `xorm:"-"`
NumRepos int
@@ -439,23 +432,20 @@ func (t *Team) IsOwnerTeam() bool {
// IsTeamMember returns true if given user is a member of team.
func (t *Team) IsMember(uid int64) bool {
- return IsTeamMember(t.OrgId, t.Id, uid)
+ return IsTeamMember(t.OrgID, t.ID, uid)
}
-func (t *Team) getRepositories(e Engine) error {
- idStrs := strings.Split(t.RepoIds, "|")
- t.Repos = make([]*Repository, 0, len(idStrs))
- for _, str := range idStrs {
- if len(str) == 0 {
- continue
- }
- id := com.StrTo(str[1:]).MustInt64()
- if id == 0 {
- continue
- }
- repo, err := getRepositoryById(e, id)
+func (t *Team) getRepositories(e Engine) (err error) {
+ teamRepos := make([]*TeamRepo, 0, t.NumRepos)
+ if err = x.Where("team_id=?", t.ID).Find(&teamRepos); err != nil {
+ return fmt.Errorf("get team-repos: %v", err)
+ }
+
+ t.Repos = make([]*Repository, 0, len(teamRepos))
+ for i := range teamRepos {
+ repo, err := getRepositoryById(e, teamRepos[i].RepoID)
if err != nil {
- return err
+ return fmt.Errorf("getRepositoryById(%d): %v", teamRepos[i].RepoID, err)
}
t.Repos = append(t.Repos, repo)
}
@@ -468,7 +458,7 @@ func (t *Team) GetRepositories() error {
}
func (t *Team) getMembers(e Engine) (err error) {
- t.Members, err = getTeamMembers(e, t.Id)
+ t.Members, err = getTeamMembers(e, t.ID)
return err
}
@@ -479,96 +469,121 @@ func (t *Team) GetMembers() (err error) {
// AddMember adds new member to team of organization.
func (t *Team) AddMember(uid int64) error {
- return AddTeamMember(t.OrgId, t.Id, uid)
+ return AddTeamMember(t.OrgID, t.ID, uid)
}
// RemoveMember removes member from team of organization.
func (t *Team) RemoveMember(uid int64) error {
- return RemoveTeamMember(t.OrgId, t.Id, uid)
+ return RemoveTeamMember(t.OrgID, t.ID, uid)
}
-// AddRepository adds new repository to team of organization.
-func (t *Team) AddRepository(repo *Repository) (err error) {
- idStr := "$" + com.ToStr(repo.Id) + "|"
- if repo.OwnerId != t.OrgId {
- return errors.New("Repository not belong to organization")
- } else if strings.Contains(t.RepoIds, idStr) {
- return nil
- }
+func (t *Team) hasRepository(e Engine, repoID int64) bool {
+ return hasTeamRepo(e, t.OrgID, t.ID, repoID)
+}
- if err = repo.GetOwner(); err != nil {
- return err
- } else if err = t.GetMembers(); err != nil {
- return err
- }
+// HasRepository returns true if given repository belong to team.
+func (t *Team) HasRepository(repoID int64) bool {
+ return HasTeamRepo(t.OrgID, t.ID, repoID)
+}
- sess := x.NewSession()
- defer sessionRelease(sess)
- if err = sess.Begin(); err != nil {
+func (t *Team) addRepository(e Engine, repo *Repository) (err error) {
+ if err = addTeamRepo(e, t.OrgID, t.ID, repo.Id); err != nil {
return err
}
t.NumRepos++
- t.RepoIds += idStr
- if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
+ if _, err = e.Id(t.ID).AllCols().Update(t); err != nil {
return err
}
- if err = repo.recalculateAccesses(sess); err != nil {
+ if err = repo.recalculateAccesses(e); err != nil {
return err
}
+ if err = t.getMembers(e); err != nil {
+ return fmt.Errorf("get team members: %v", err)
+ }
for _, u := range t.Members {
- if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
+ if err = watchRepo(e, u.Id, repo.Id, true); err != nil {
return err
}
}
- return sess.Commit()
-}
-
-func (t *Team) HasRepository(repo *Repository) bool {
- idStr := "$" + com.ToStr(repo.Id) + "|"
- return strings.Contains(t.RepoIds, idStr)
+ return nil
}
-// RemoveRepository removes repository from team of organization.
-func (t *Team) RemoveRepository(repoId int64) error {
- idStr := "$" + com.ToStr(repoId) + "|"
- if !strings.Contains(t.RepoIds, idStr) {
+// AddRepository adds new repository to team of organization.
+func (t *Team) AddRepository(repo *Repository) (err error) {
+ if repo.OwnerId != t.OrgID {
+ return errors.New("Repository does not belong to organization")
+ } else if t.HasRepository(repo.Id) {
return nil
}
- repo, err := GetRepositoryById(repoId)
- if err != nil {
+ sess := x.NewSession()
+ defer sessionRelease(sess)
+ if err = sess.Begin(); err != nil {
return err
}
- if err = repo.GetOwner(); err != nil {
- return err
- } else if err = t.GetMembers(); err != nil {
+ if err = t.addRepository(sess, repo); err != nil {
return err
}
- sess := x.NewSession()
- defer sessionRelease(sess)
- if err = sess.Begin(); err != nil {
+ return sess.Commit()
+}
+
+func (t *Team) removeRepository(e Engine, repo *Repository) (err error) {
+ if err = removeTeamRepo(e, t.ID, repo.Id); err != nil {
return err
}
t.NumRepos--
- t.RepoIds = strings.Replace(t.RepoIds, idStr, "", 1)
- if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
+ if _, err = e.Id(t.ID).AllCols().Update(t); err != nil {
return err
}
- if err = repo.recalculateAccesses(sess); err != nil {
+ if err = repo.recalculateAccesses(e); err != nil {
return err
}
+ if err = t.getMembers(e); err != nil {
+ return fmt.Errorf("get team members: %v", err)
+ }
for _, u := range t.Members {
- if err = watchRepo(sess, u.Id, repo.Id, false); err != nil {
+ has, err := hasAccess(e, u, repo, ACCESS_MODE_READ)
+ if err != nil {
return err
+ } else if has {
+ continue
}
+
+ if err = watchRepo(e, u.Id, repo.Id, false); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+// RemoveRepository removes repository from team of organization.
+func (t *Team) RemoveRepository(repoID int64) error {
+ if !t.HasRepository(repoID) {
+ return nil
+ }
+
+ repo, err := GetRepositoryById(repoID)
+ if err != nil {
+ return err
+ }
+
+ sess := x.NewSession()
+ defer sessionRelease(sess)
+ if err = sess.Begin(); err != nil {
+ return err
+ }
+
+ if err = t.removeRepository(sess, repo); err != nil {
+ return err
}
return sess.Commit()
@@ -581,7 +596,7 @@ func NewTeam(t *Team) error {
return ErrTeamNameIllegal
}
- has, err := x.Id(t.OrgId).Get(new(User))
+ has, err := x.Id(t.OrgID).Get(new(User))
if err != nil {
return err
} else if !has {
@@ -589,7 +604,7 @@ func NewTeam(t *Team) error {
}
t.LowerName = strings.ToLower(t.Name)
- has, err = x.Where("org_id=?", t.OrgId).And("lower_name=?", t.LowerName).Get(new(Team))
+ has, err = x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).Get(new(Team))
if err != nil {
return err
} else if has {
@@ -608,7 +623,7 @@ func NewTeam(t *Team) error {
}
// Update organization number of teams.
- if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgId); err != nil {
+ if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgID); err != nil {
sess.Rollback()
return err
}
@@ -617,7 +632,7 @@ func NewTeam(t *Team) error {
func getTeam(e Engine, orgId int64, name string) (*Team, error) {
t := &Team{
- OrgId: orgId,
+ OrgID: orgId,
LowerName: strings.ToLower(name),
}
has, err := e.Get(t)
@@ -667,7 +682,7 @@ func UpdateTeam(t *Team, authChanged bool) (err error) {
}
t.LowerName = strings.ToLower(t.Name)
- if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
+ if _, err = sess.Id(t.ID).AllCols().Update(t); err != nil {
return err
}
@@ -697,7 +712,7 @@ func DeleteTeam(t *Team) error {
}
// Get organization.
- org, err := GetUserById(t.OrgId)
+ org, err := GetUserById(t.OrgID)
if err != nil {
return err
}
@@ -716,16 +731,16 @@ func DeleteTeam(t *Team) error {
}
// Delete team-user.
- if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.Id).Delete(new(TeamUser)); err != nil {
+ if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.ID).Delete(new(TeamUser)); err != nil {
return err
}
// Delete team.
- if _, err = sess.Id(t.Id).Delete(new(Team)); err != nil {
+ if _, err = sess.Id(t.ID).Delete(new(Team)); err != nil {
return err
}
// Update organization number of teams.
- if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams - 1 WHERE id = ?", t.OrgId); err != nil {
+ if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil {
return err
}
@@ -741,20 +756,20 @@ func DeleteTeam(t *Team) error {
// TeamUser represents an team-user relation.
type TeamUser struct {
- Id int64
- Uid int64
- OrgId int64 `xorm:"INDEX"`
- TeamId int64
+ ID int64 `xorm:"pk autoincr"`
+ OrgID int64 `xorm:"INDEX"`
+ TeamID int64 `xorm:"UNIQUE(s)"`
+ Uid int64 `xorm:"UNIQUE(s)"`
}
-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))
+func isTeamMember(e Engine, orgID, teamID, uid int64) bool {
+ has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("uid=?", uid).Get(new(TeamUser))
return has
}
// IsTeamMember returns true if given user is a member of team.
-func IsTeamMember(orgId, teamId, uid int64) bool {
- return isTeamMember(x, orgId, teamId, uid)
+func IsTeamMember(orgID, teamID, uid int64) bool {
+ return isTeamMember(x, orgID, teamID, uid)
}
func getTeamMembers(e Engine, teamID int64) ([]*User, error) {
@@ -777,7 +792,7 @@ func getUserTeams(e Engine, orgId, uid int64) ([]*Team, error) {
ts := make([]*Team, len(tus))
for i, tu := range tus {
t := new(Team)
- has, err := e.Id(tu.TeamId).Get(t)
+ has, err := e.Id(tu.TeamID).Get(t)
if err != nil {
return nil, err
} else if !has {
@@ -822,13 +837,13 @@ func AddTeamMember(orgId, teamId, uid int64) error {
tu := &TeamUser{
Uid: uid,
- OrgId: orgId,
- TeamId: teamId,
+ OrgID: orgId,
+ TeamID: teamId,
}
if _, err = sess.Insert(tu); err != nil {
return err
- } else if _, err = sess.Id(t.Id).Update(t); err != nil {
+ } else if _, err = sess.Id(t.ID).Update(t); err != nil {
return err
}
@@ -848,7 +863,7 @@ func AddTeamMember(orgId, teamId, uid int64) error {
if t.IsOwnerTeam() {
ou.IsOwner = true
}
- if _, err = sess.Id(ou.Id).AllCols().Update(ou); err != nil {
+ if _, err = sess.Id(ou.ID).AllCols().Update(ou); err != nil {
return err
}
@@ -885,13 +900,13 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error {
tu := &TeamUser{
Uid: uid,
- OrgId: orgId,
- TeamId: teamId,
+ OrgID: orgId,
+ TeamID: teamId,
}
if _, err := e.Delete(tu); err != nil {
return err
- } else if _, err = e.Id(t.Id).AllCols().Update(t); err != nil {
+ } else if _, err = e.Id(t.ID).AllCols().Update(t); err != nil {
return err
}
@@ -912,7 +927,7 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error {
if t.IsOwnerTeam() {
ou.IsOwner = false
}
- if _, err = e.Id(ou.Id).AllCols().Update(ou); err != nil {
+ if _, err = e.Id(ou.ID).AllCols().Update(ou); err != nil {
return err
}
return nil
@@ -921,13 +936,64 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error {
// RemoveTeamMember removes member from given team of given organization.
func RemoveTeamMember(orgId, teamId, uid int64) error {
sess := x.NewSession()
- defer sess.Close()
+ defer sessionRelease(sess)
if err := sess.Begin(); err != nil {
return err
}
if err := removeTeamMember(sess, orgId, teamId, uid); err != nil {
- sess.Rollback()
return err
}
return sess.Commit()
}
+
+// ___________ __________
+// \__ ___/___ _____ _____\______ \ ____ ______ ____
+// | |_/ __ \\__ \ / \| _// __ \\____ \ / _ \
+// | |\ ___/ / __ \| Y Y \ | \ ___/| |_> > <_> )
+// |____| \___ >____ /__|_| /____|_ /\___ > __/ \____/
+// \/ \/ \/ \/ \/|__|
+
+// TeamRepo represents an team-repository relation.
+type TeamRepo struct {
+ ID int64 `xorm:"pk autoincr"`
+ OrgID int64 `xorm:"INDEX"`
+ TeamID int64 `xorm:"UNIQUE(s)"`
+ RepoID int64 `xorm:"UNIQUE(s)"`
+}
+
+func hasTeamRepo(e Engine, orgID, teamID, repoID int64) bool {
+ has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("repo_id=?", repoID).Get(new(TeamRepo))
+ return has
+}
+
+// HasTeamRepo returns true if given repository belongs to team.
+func HasTeamRepo(orgID, teamID, repoID int64) bool {
+ return hasTeamRepo(x, orgID, teamID, repoID)
+}
+
+func addTeamRepo(e Engine, orgID, teamID, repoID int64) error {
+ _, err := e.InsertOne(&TeamRepo{
+ OrgID: orgID,
+ TeamID: teamID,
+ RepoID: repoID,
+ })
+ return err
+}
+
+// AddTeamRepo adds new repository relation to team.
+func AddTeamRepo(orgID, teamID, repoID int64) error {
+ return addTeamRepo(x, orgID, teamID, repoID)
+}
+
+func removeTeamRepo(e Engine, teamID, repoID int64) error {
+ _, err := e.Delete(&TeamRepo{
+ TeamID: teamID,
+ RepoID: repoID,
+ })
+ return err
+}
+
+// RemoveTeamRepo deletes repository relation to team.
+func RemoveTeamRepo(teamID, repoID int64) error {
+ return removeTeamRepo(x, teamID, repoID)
+}
diff --git a/models/repo.go b/models/repo.go
index fd00823a23..7f87bbb2a7 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -154,7 +154,6 @@ type Repository struct {
IsPrivate bool
IsBare bool
- IsGoget bool
IsMirror bool
*Mirror `xorm:"-"`
@@ -515,7 +514,7 @@ func initRepository(e Engine, f string, u *User, repo *Repository, initReadme bo
}
// CreateRepository creates a repository for given user or organization.
-func CreateRepository(u *User, name, desc, lang, license string, private, mirror, initReadme bool) (*Repository, error) {
+func CreateRepository(u *User, name, desc, lang, license string, isPrivate, isMirror, initReadme bool) (*Repository, error) {
if !IsLegalName(name) {
return nil, ErrRepoNameIllegal
}
@@ -533,7 +532,7 @@ func CreateRepository(u *User, name, desc, lang, license string, private, mirror
Name: name,
LowerName: strings.ToLower(name),
Description: desc,
- IsPrivate: private,
+ IsPrivate: isPrivate,
}
sess := x.NewSession()
@@ -559,34 +558,22 @@ func CreateRepository(u *User, name, desc, lang, license string, private, mirror
// Update owner team info and count.
t, err := u.getOwnerTeam(sess)
if err != nil {
- return nil, fmt.Errorf("get owner team: %v", err)
- } else if err = t.getMembers(sess); err != nil {
- return nil, fmt.Errorf("get team members: %v", err)
- }
-
- for _, u := range t.Members {
- if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
- return nil, fmt.Errorf("watch repository: %v", err)
- }
- }
-
- t.RepoIds += "$" + com.ToStr(repo.Id) + "|"
- t.NumRepos++
- if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
- return nil, err
+ return nil, fmt.Errorf("getOwnerTeam: %v", err)
+ } else if err = t.addRepository(sess, repo); err != nil {
+ return nil, fmt.Errorf("addRepository: %v", err)
}
} else {
if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
- return nil, fmt.Errorf("watch repository 2: %v", err)
+ return nil, fmt.Errorf("watchRepo: %v", err)
}
}
if err = newRepoAction(sess, u, repo); err != nil {
- return nil, fmt.Errorf("new repository action: %v", err)
+ return nil, fmt.Errorf("newRepoAction: %v", err)
}
// No need for init mirror.
- if !mirror {
+ if !isMirror {
repoPath := RepoPath(u.Name, repo.Name)
if err = initRepository(sess, repoPath, u, repo, initReadme, lang, license); err != nil {
if err2 := os.RemoveAll(repoPath); err2 != nil {
@@ -641,14 +628,14 @@ func RepoPath(userName, repoName string) string {
}
// TransferOwnership transfers all corresponding setting from old user to new one.
-func TransferOwnership(u *User, newOwner string, repo *Repository) error {
- newUser, err := GetUserByName(newOwner)
+func TransferOwnership(u *User, newOwnerName string, repo *Repository) error {
+ newOwner, err := GetUserByName(newOwnerName)
if err != nil {
- return fmt.Errorf("fail to get new owner(%s): %v", newOwner, err)
+ return fmt.Errorf("get new owner(%s): %v", newOwnerName, err)
}
// Check if new owner has repository with same name.
- has, err := IsRepositoryExist(newUser, repo.Name)
+ has, err := IsRepositoryExist(newOwner, repo.Name)
if err != nil {
return err
} else if has {
@@ -664,27 +651,50 @@ func TransferOwnership(u *User, newOwner string, repo *Repository) error {
owner := repo.Owner
// Update repository.
- repo.OwnerId = newUser.Id
- repo.Owner = newUser
+ repo.OwnerId = newOwner.Id
+ repo.Owner = newOwner
if _, err := sess.Id(repo.Id).Update(repo); err != nil {
return err
}
+ // Remove redundant collaborators
+ collaborators, err := repo.GetCollaborators()
+ if err != nil {
+ return err
+ }
+ for _, c := range collaborators {
+ if c.Id == newOwner.Id || newOwner.IsOrgMember(c.Id) {
+ if _, err = sess.Delete(&Collaboration{RepoID: repo.Id, UserID: c.Id}); err != nil {
+ return err
+ }
+ }
+ }
+
+ if newOwner.IsOrganization() {
+ // Update owner team info and count.
+ t, err := newOwner.GetOwnerTeam()
+ if err != nil {
+ return err
+ } else if err = t.addRepository(sess, repo); err != nil {
+ return err
+ }
+ }
+
// Update user repository number.
- if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?", newUser.Id); err != nil {
+ if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?", newOwner.Id); err != nil {
return err
} else if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", owner.Id); err != nil {
return err
} else if err = repo.recalculateAccesses(sess); err != nil {
return err
- } else if err = watchRepo(sess, newUser.Id, repo.Id, true); err != nil {
+ } else if err = watchRepo(sess, newOwner.Id, repo.Id, true); err != nil {
return err
- } else if err = transferRepoAction(sess, u, newUser, repo); err != nil {
+ } else if err = transferRepoAction(sess, u, owner, newOwner, repo); err != nil {
return err
}
// Change repository directory name.
- if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newUser.Name, repo.Name)); err != nil {
+ if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil {
return err
}
@@ -722,8 +732,8 @@ func UpdateRepository(repo *Repository) error {
}
// DeleteRepository deletes a repository for a user or organization.
-func DeleteRepository(uid, repoId int64, userName string) error {
- repo := &Repository{Id: repoId, OwnerId: uid}
+func DeleteRepository(uid, repoID int64, userName string) error {
+ repo := &Repository{Id: repoID, OwnerId: uid}
has, err := x.Get(repo)
if err != nil {
return err
@@ -749,68 +759,66 @@ func DeleteRepository(uid, repoId int64, userName string) error {
}
if org.IsOrganization() {
- idStr := "$" + com.ToStr(repoId) + "|"
for _, t := range org.Teams {
- if !strings.Contains(t.RepoIds, idStr) {
+ if !t.hasRepository(sess, repoID) {
continue
- }
- t.NumRepos--
- t.RepoIds = strings.Replace(t.RepoIds, idStr, "", 1)
- if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
+ } else if err = t.removeRepository(sess, repo); err != nil {
return err
}
}
}
- if _, err = sess.Delete(&Repository{Id: repoId}); err != nil {
+ if _, err = sess.Delete(&Repository{Id: repoID}); err != nil {
return err
} else if _, err := sess.Delete(&Access{RepoID: repo.Id}); err != nil {
return err
} else if _, err := sess.Delete(&Action{RepoId: repo.Id}); err != nil {
return err
- } else if _, err = sess.Delete(&Watch{RepoId: repoId}); err != nil {
+ } else if _, err = sess.Delete(&Watch{RepoId: repoID}); err != nil {
return err
- } else if _, err = sess.Delete(&Mirror{RepoId: repoId}); err != nil {
+ } else if _, err = sess.Delete(&Mirror{RepoId: repoID}); err != nil {
return err
- } else if _, err = sess.Delete(&IssueUser{RepoId: repoId}); err != nil {
+ } else if _, err = sess.Delete(&IssueUser{RepoId: repoID}); err != nil {
return err
- } else if _, err = sess.Delete(&Milestone{RepoId: repoId}); err != nil {
+ } else if _, err = sess.Delete(&Milestone{RepoId: repoID}); err != nil {
return err
- } else if _, err = sess.Delete(&Release{RepoId: repoId}); err != nil {
+ } else if _, err = sess.Delete(&Release{RepoId: repoID}); err != nil {
+ return err
+ } else if _, err = sess.Delete(&Collaboration{RepoID: repoID}); err != nil {
return err
}
// Delete comments.
- if err = x.Iterate(&Issue{RepoId: repoId}, func(idx int, bean interface{}) error {
- issue := bean.(*Issue)
- if _, err = sess.Delete(&Comment{IssueId: issue.Id}); err != nil {
+ issues := make([]*Issue, 0, 25)
+ if err = sess.Where("repo_id=?", repoID).Find(&issues); err != nil {
+ return err
+ }
+ for i := range issues {
+ if _, err = sess.Delete(&Comment{IssueId: issues[i].Id}); err != nil {
return err
}
- return nil
- }); err != nil {
- return err
}
- if _, err = sess.Delete(&Issue{RepoId: repoId}); err != nil {
+ if _, err = sess.Delete(&Issue{RepoId: repoID}); err != nil {
return err
}
if repo.IsFork {
- if _, err = sess.Exec("UPDATE `repository` SET num_forks = num_forks - 1 WHERE id = ?", repo.ForkId); err != nil {
+ if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkId); err != nil {
return err
}
}
- if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", uid); err != nil {
+ if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", uid); err != nil {
return err
}
// Remove repository files.
if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil {
- desc := fmt.Sprintf("Fail to delete repository files(%s/%s): %v", userName, repo.Name, err)
+ desc := fmt.Sprintf("delete repository files(%s/%s): %v", userName, repo.Name, err)
log.Warn(desc)
if err = CreateRepositoryNotice(desc); err != nil {
- log.Error(4, "Fail to add notice: %v", err)
+ log.Error(4, "add notice: %v", err)
}
}
@@ -1314,33 +1322,21 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (*Repositor
// Update owner team info and count.
t, err := u.getOwnerTeam(sess)
if err != nil {
- return nil, fmt.Errorf("get owner team: %v", err)
- } else if err = t.getMembers(sess); err != nil {
- return nil, fmt.Errorf("get team members: %v", err)
- }
-
- for _, u := range t.Members {
- if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
- return nil, fmt.Errorf("watch repository: %v", err)
- }
- }
-
- t.RepoIds += "$" + com.ToStr(repo.Id) + "|"
- t.NumRepos++
- if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
- return nil, err
+ return nil, fmt.Errorf("getOwnerTeam: %v", err)
+ } else if err = t.addRepository(sess, repo); err != nil {
+ return nil, fmt.Errorf("addRepository: %v", err)
}
} else {
if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
- return nil, fmt.Errorf("watch repository 2: %v", err)
+ return nil, fmt.Errorf("watchRepo: %v", err)
}
}
if err = newRepoAction(sess, u, repo); err != nil {
- return nil, fmt.Errorf("new repository action: %v", err)
+ return nil, fmt.Errorf("newRepoAction: %v", err)
}
- if _, err = sess.Exec("UPDATE `repository` SET num_forks = num_forks + 1 WHERE id = ?", oldRepo.Id); err != nil {
+ if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", oldRepo.Id); err != nil {
return nil, err
}
diff --git a/models/user.go b/models/user.go
index 3c439fff06..f5bec2e83a 100644
--- a/models/user.go
+++ b/models/user.go
@@ -231,7 +231,7 @@ func (u *User) GetOrganizations() error {
u.Orgs = make([]*User, len(ous))
for i, ou := range ous {
- u.Orgs[i], err = GetUserById(ou.OrgId)
+ u.Orgs[i], err = GetUserById(ou.OrgID)
if err != nil {
return err
}
@@ -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 {
@@ -401,7 +403,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 {
@@ -578,7 +580,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)
@@ -592,7 +594,6 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
}
isPrimaryFound := false
-
for _, email := range emails {
if email.Email == u.Email {
isPrimaryFound = true
@@ -605,7 +606,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
}
@@ -855,7 +860,7 @@ func UpdateMentions(userNames []string, issueId int64) error {
}
for _, orgUser := range orgUsers {
- tempIds = append(tempIds, orgUser.Id)
+ tempIds = append(tempIds, orgUser.ID)
}
ids = append(ids, tempIds...)
diff --git a/modules/auth/repo_form.go b/modules/auth/repo_form.go
index 36e62f04fb..2902a92f2e 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 3c0ff65174..b616a460ff 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/template.go b/modules/base/template.go
index f3fa138578..cfcabb71a2 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 5043364cec..55e6dffd96 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/git/signature.go b/modules/git/signature.go
index 20f647d266..ad9c1b39b7 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 6a23e5d09e..fc6ec2fa86 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/context.go b/modules/middleware/context.go
index 28be3a3025..dc3b5cad16 100644
--- a/modules/middleware/context.go
+++ b/modules/middleware/context.go
@@ -38,29 +38,7 @@ type Context struct {
IsSigned bool
IsBasicAuth bool
- Repo struct {
- IsOwner bool
- IsTrueOwner bool
- IsWatching bool
- IsBranch bool
- IsTag bool
- IsCommit bool
- IsAdmin bool // Current user is admin level.
- HasAccess bool
- Repository *models.Repository
- Owner *models.User
- Commit *git.Commit
- Tag *git.Tag
- GitRepo *git.Repository
- BranchName string
- TagName string
- TreeName string
- CommitId string
- RepoLink string
- CloneLink models.CloneLink
- CommitsCount int
- Mirror *models.Mirror
- }
+ Repo RepoContext
Org struct {
IsOwner bool
@@ -73,6 +51,37 @@ type Context struct {
}
}
+type RepoContext struct {
+ AccessMode models.AccessMode
+ IsWatching bool
+ IsBranch bool
+ IsTag bool
+ IsCommit bool
+ Repository *models.Repository
+ Owner *models.User
+ Commit *git.Commit
+ Tag *git.Tag
+ GitRepo *git.Repository
+ BranchName string
+ TagName string
+ TreeName string
+ CommitId string
+ RepoLink string
+ CloneLink models.CloneLink
+ CommitsCount int
+ Mirror *models.Mirror
+}
+
+// Return if the current user has write access for this repository
+func (r RepoContext) IsOwner() bool {
+ return r.AccessMode >= models.ACCESS_MODE_WRITE
+}
+
+// Return if the current user has read access for this repository
+func (r RepoContext) HasAccess() bool {
+ return r.AccessMode >= models.ACCESS_MODE_READ
+}
+
// HasError returns true if error occurs in form validation.
func (ctx *Context) HasApiError() bool {
hasErr, ok := ctx.Data["HasError"]
@@ -130,6 +139,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 bd298819d7..3350c03d22 100644
--- a/modules/middleware/repo.go
+++ b/modules/middleware/repo.go
@@ -58,24 +58,19 @@ func ApiRepoAssignment() macaron.Handler {
return
}
- if ctx.IsSigned {
- mode, err := models.AccessLevel(ctx.User, repo)
- if err != nil {
- ctx.JSON(500, &base.ApiJsonErr{"AccessLevel: " + err.Error(), base.DOC_URL})
- return
- }
-
- ctx.Repo.IsOwner = mode >= models.ACCESS_MODE_WRITE
- ctx.Repo.IsAdmin = mode >= models.ACCESS_MODE_READ
- ctx.Repo.IsTrueOwner = mode >= models.ACCESS_MODE_OWNER
+ mode, err := models.AccessLevel(ctx.User, repo)
+ if err != nil {
+ ctx.JSON(500, &base.ApiJsonErr{"AccessLevel: " + err.Error(), base.DOC_URL})
+ return
}
+ ctx.Repo.AccessMode = mode
+
// Check access.
- if repo.IsPrivate && !ctx.Repo.IsOwner {
+ if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE {
ctx.Error(404)
return
}
- ctx.Repo.HasAccess = true
ctx.Repo.Repository = repo
}
@@ -239,26 +234,18 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
return
}
- if ctx.IsSigned {
- mode, err := models.AccessLevel(ctx.User, repo)
- if err != nil {
- ctx.Handle(500, "AccessLevel", err)
- return
- }
- ctx.Repo.IsOwner = mode >= models.ACCESS_MODE_WRITE
- ctx.Repo.IsAdmin = mode >= models.ACCESS_MODE_READ
- ctx.Repo.IsTrueOwner = mode >= models.ACCESS_MODE_OWNER
- if !ctx.Repo.IsTrueOwner && ctx.Repo.Owner.IsOrganization() {
- ctx.Repo.IsTrueOwner = ctx.Repo.Owner.IsOwnedBy(ctx.User.Id)
- }
+ mode, err := models.AccessLevel(ctx.User, repo)
+ if err != nil {
+ ctx.Handle(500, "AccessLevel", err)
+ return
}
+ ctx.Repo.AccessMode = mode
// Check access.
- if repo.IsPrivate && !ctx.Repo.IsOwner {
+ if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE {
ctx.Handle(404, "no access right", err)
return
}
- ctx.Repo.HasAccess = true
ctx.Data["HasAccess"] = true
@@ -306,8 +293,8 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
ctx.Data["Title"] = u.Name + "/" + repo.Name
ctx.Data["Repository"] = repo
ctx.Data["Owner"] = ctx.Repo.Repository.Owner
- ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
- ctx.Data["IsRepositoryTrueOwner"] = ctx.Repo.IsTrueOwner
+ ctx.Data["IsRepositoryOwner"] = ctx.Repo.AccessMode >= models.ACCESS_MODE_WRITE
+ ctx.Data["IsRepositoryAdmin"] = ctx.Repo.AccessMode >= models.ACCESS_MODE_ADMIN
ctx.Data["DisableSSH"] = setting.DisableSSH
ctx.Repo.CloneLink, err = repo.CloneLink()
@@ -317,8 +304,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)
}
@@ -362,9 +348,9 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
}
}
-func RequireTrueOwner() macaron.Handler {
+func RequireAdmin() macaron.Handler {
return func(ctx *Context) {
- if !ctx.Repo.IsTrueOwner && !ctx.Repo.IsAdmin {
+ if ctx.Repo.AccessMode < models.ACCESS_MODE_ADMIN {
if !ctx.IsSigned {
ctx.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl)
ctx.Redirect(setting.AppSubUrl + "/user/login")
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 795bcc5ba2..6a36105691 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -245,7 +245,10 @@ func NewConfigContext() {
ReverseProxyAuthUser = sec.Key("REVERSE_PROXY_AUTHENTICATION_USER").MustString("X-WEBAUTH-USER")
sec = Cfg.Section("attachment")
- AttachmentPath = path.Join(workDir, sec.Key("PATH").MustString("data/attachments"))
+ 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)
@@ -302,7 +305,10 @@ func NewConfigContext() {
sec = Cfg.Section("picture")
PictureService = sec.Key("SERVICE").In("server", []string{"server"})
- AvatarUploadPath = path.Join(workDir, sec.Key("AVATAR_UPLOAD_PATH").MustString("data/avatars"))
+ 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":
diff --git a/public/ng/css/gogs.css b/public/ng/css/gogs.css
index 9f6cf12f97..43931e94d3 100644
--- a/public/ng/css/gogs.css
+++ b/public/ng/css/gogs.css
@@ -1066,9 +1066,6 @@ The register and sign-in page style
#repo-header-download-drop .btn > i {
margin-right: 6px;
}
-#repo-header-download-drop input {
- cursor: default;
-}
#repo-header-download-drop button,
#repo-header-download-drop input {
font-size: 11px;
@@ -1089,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;
diff --git a/public/ng/js/gogs.js b/public/ng/js/gogs.js
index a6b9753e17..c5fd719c32 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 d683d03341..63c25d06b6 100644
--- a/public/ng/less/gogs/repository.less
+++ b/public/ng/less/gogs/repository.less
@@ -81,9 +81,6 @@
.btn>i {
margin-right: 6px;
}
- input {
- cursor: default;
- }
button, input {
font-size: 11px;
}
@@ -104,6 +101,7 @@
border-right: none;
width: 190px;
border-left: none;
+ cursor: default;
}
#repo-clone-help {
clear: both;
diff --git a/routers/api/v1/repo.go b/routers/api/v1/repo.go
index f5128e4746..eb9908911f 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/api/v1/repo_file.go b/routers/api/v1/repo_file.go
index a049904f95..73f97b2cae 100644
--- a/routers/api/v1/repo_file.go
+++ b/routers/api/v1/repo_file.go
@@ -12,7 +12,7 @@ import (
)
func GetRepoRawFile(ctx *middleware.Context) {
- if ctx.Repo.Repository.IsPrivate && !ctx.Repo.HasAccess {
+ if !ctx.Repo.HasAccess() {
ctx.Error(404)
return
}
diff --git a/routers/install.go b/routers/install.go
index a3583a1a98..a7828e351c 100644
--- a/routers/install.go
+++ b/routers/install.go
@@ -189,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)
diff --git a/routers/org/setting.go b/routers/org/setting.go
index 41ec4a2141..c638a032e7 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 2fbb1480d1..69f2734c64 100644
--- a/routers/org/teams.go
+++ b/routers/org/teams.go
@@ -181,7 +181,7 @@ func NewTeamPost(ctx *middleware.Context, form auth.CreateTeamForm) {
org := ctx.Org.Organization
t := &models.Team{
- OrgId: org.Id,
+ OrgID: org.Id,
Name: form.TeamName,
Description: form.Description,
Authorize: auth,
diff --git a/routers/repo/http.go b/routers/repo/http.go
index 034b5a7b5e..d47d73ef05 100644
--- a/routers/repo/http.go
+++ b/routers/repo/http.go
@@ -158,6 +158,11 @@ func Http(ctx *middleware.Context) {
return
}
}
+
+ if !isPull && repo.IsMirror {
+ ctx.Handle(401, "can't push to mirror", nil)
+ return
+ }
}
}
diff --git a/routers/repo/issue.go b/routers/repo/issue.go
index bf39d9aba6..40e9338970 100644
--- a/routers/repo/issue.go
+++ b/routers/repo/issue.go
@@ -230,7 +230,7 @@ func CreateIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) {
}
// Only collaborators can assign.
- if !ctx.Repo.IsOwner {
+ if !ctx.Repo.IsOwner() {
form.AssigneeId = 0
}
issue := &models.Issue{
@@ -434,7 +434,7 @@ func ViewIssue(ctx *middleware.Context) {
ctx.Data["Title"] = issue.Name
ctx.Data["Issue"] = issue
ctx.Data["Comments"] = comments
- ctx.Data["IsIssueOwner"] = ctx.Repo.IsOwner || (ctx.IsSigned && issue.PosterId == ctx.User.Id)
+ ctx.Data["IsIssueOwner"] = ctx.Repo.IsOwner() || (ctx.IsSigned && issue.PosterId == ctx.User.Id)
ctx.Data["IsRepoToolbarIssues"] = true
ctx.Data["IsRepoToolbarIssuesList"] = false
ctx.HTML(200, ISSUE_VIEW)
@@ -457,7 +457,7 @@ func UpdateIssue(ctx *middleware.Context, form auth.CreateIssueForm) {
return
}
- if ctx.User.Id != issue.PosterId && !ctx.Repo.IsOwner {
+ if ctx.User.Id != issue.PosterId && !ctx.Repo.IsOwner() {
ctx.Error(403)
return
}
@@ -484,7 +484,7 @@ func UpdateIssue(ctx *middleware.Context, form auth.CreateIssueForm) {
}
func UpdateIssueLabel(ctx *middleware.Context) {
- if !ctx.Repo.IsOwner {
+ if !ctx.Repo.IsOwner() {
ctx.Error(403)
return
}
@@ -560,7 +560,7 @@ func UpdateIssueLabel(ctx *middleware.Context) {
}
func UpdateIssueMilestone(ctx *middleware.Context) {
- if !ctx.Repo.IsOwner {
+ if !ctx.Repo.IsOwner() {
ctx.Error(403)
return
}
@@ -606,7 +606,7 @@ func UpdateIssueMilestone(ctx *middleware.Context) {
}
func UpdateAssignee(ctx *middleware.Context) {
- if !ctx.Repo.IsOwner {
+ if !ctx.Repo.IsOwner() {
ctx.Error(403)
return
}
@@ -752,7 +752,7 @@ func Comment(ctx *middleware.Context) {
// Check if issue owner changes the status of issue.
var newStatus string
- if ctx.Repo.IsOwner || issue.PosterId == ctx.User.Id {
+ if ctx.Repo.IsOwner() || issue.PosterId == ctx.User.Id {
newStatus = ctx.Query("change_status")
}
if len(newStatus) > 0 {
diff --git a/routers/repo/release.go b/routers/repo/release.go
index 591810cc5f..52d78b1967 100644
--- a/routers/repo/release.go
+++ b/routers/repo/release.go
@@ -41,7 +41,7 @@ func Releases(ctx *middleware.Context) {
tags := make([]*models.Release, len(rawTags))
for i, rawTag := range rawTags {
for j, rel := range rels {
- if rel == nil || (rel.IsDraft && !ctx.Repo.IsOwner) {
+ if rel == nil || (rel.IsDraft && !ctx.Repo.IsOwner()) {
continue
}
if rel.TagName == rawTag {
@@ -140,7 +140,7 @@ func Releases(ctx *middleware.Context) {
}
func NewRelease(ctx *middleware.Context) {
- if !ctx.Repo.IsOwner {
+ if !ctx.Repo.IsOwner() {
ctx.Handle(403, "release.ReleasesNew", nil)
return
}
@@ -153,7 +153,7 @@ func NewRelease(ctx *middleware.Context) {
}
func NewReleasePost(ctx *middleware.Context, form auth.NewReleaseForm) {
- if !ctx.Repo.IsOwner {
+ if !ctx.Repo.IsOwner() {
ctx.Handle(403, "release.ReleasesNew", nil)
return
}
@@ -211,7 +211,7 @@ func NewReleasePost(ctx *middleware.Context, form auth.NewReleaseForm) {
}
func EditRelease(ctx *middleware.Context) {
- if !ctx.Repo.IsOwner {
+ if !ctx.Repo.IsOwner() {
ctx.Handle(403, "release.ReleasesEdit", nil)
return
}
@@ -234,7 +234,7 @@ func EditRelease(ctx *middleware.Context) {
}
func EditReleasePost(ctx *middleware.Context, form auth.EditReleaseForm) {
- if !ctx.Repo.IsOwner {
+ if !ctx.Repo.IsOwner() {
ctx.Handle(403, "release.EditReleasePost", nil)
return
}
diff --git a/routers/repo/repo.go b/routers/repo/repo.go
index 48f7b09bc0..6b84a389d5 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)
@@ -343,7 +349,7 @@ func Action(ctx *middleware.Context) {
case "unstar":
err = models.StarRepo(ctx.User.Id, ctx.Repo.Repository.Id, false)
case "desc":
- if !ctx.Repo.IsOwner {
+ if !ctx.Repo.IsOwner() {
ctx.Error(404)
return
}
diff --git a/routers/repo/setting.go b/routers/repo/setting.go
index a6f50d3068..e2b8968375 100644
--- a/routers/repo/setting.go
+++ b/routers/repo/setting.go
@@ -83,7 +83,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
@@ -109,7 +108,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 9ed44e353c..5dacaf8c79 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 953e61138f..a44d3b7e5d 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 0000000000..ff2f57360b
--- /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 3e22111f8c..4758bb670f 100644
--- a/templates/.VERSION
+++ b/templates/.VERSION
@@ -1 +1 @@
-0.5.14.0213 Beta \ No newline at end of file
+0.5.15.0223 Beta \ No newline at end of file
diff --git a/templates/admin/auth/list.tmpl b/templates/admin/auth/list.tmpl
index aba516b8eb..ec701a8f8c 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/org/list.tmpl b/templates/admin/org/list.tmpl
index b522dc08a3..ce5083a0ae 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 88e16a4337..981e2ef72b 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 d42d52910e..1dd5553eb5 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 7775933ca9..cb3951ea2c 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/head.tmpl b/templates/ng/base/head.tmpl
index 40a7d28ff2..f2a235bd43 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 1bbb092bf5..1649b92090 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 4929a88198..fdce06a298 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}}
- <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)}}
+ <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 11d32d7f67..1285c4ab94 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 1ed7acb56e..1179ede620 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 2a1409a6e8..c050b6238d 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 443e002d59..f261da55a0 100644
--- a/templates/repo/diff.tmpl
+++ b/templates/repo/diff.tmpl
@@ -105,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 a0b927be60..21f9cea882 100644
--- a/templates/repo/header.tmpl
+++ b/templates/repo/header.tmpl
@@ -49,7 +49,7 @@
</a>
</li>
<li id="repo-header-fork">
- <a id="repo-header-fork-btn" {{if or (not $.IsRepositoryTrueOwner) $.Owner.IsOrganization}}href="{{AppSubUrl}}/repo/fork?fork_id={{.Id}}"{{end}}>
+ <a id="repo-header-fork-btn" {{if or (not $.IsRepositoryAdmin) $.Owner.IsOrganization}}href="{{AppSubUrl}}/repo/fork?fork_id={{.Id}}"{{end}}>
<button class="btn btn-gray text-bold btn-radius">
<i class="octicon octicon-repo-forked"></i>{{$.i18n.Tr "repo.fork"}}
<span class="num">{{.NumForks}}</span>
diff --git a/templates/repo/migrate.tmpl b/templates/repo/migrate.tmpl
index b28d06475c..5869be1558 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 093e937553..41683f8450 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/repo/sidebar.tmpl b/templates/repo/sidebar.tmpl
index 9d6abb47bc..1609603821 100644
--- a/templates/repo/sidebar.tmpl
+++ b/templates/repo/sidebar.tmpl
@@ -20,7 +20,7 @@
<!-- <li>
<a class="radius" href="#"><i class="octicon octicon-organization"></i>contributors <span class="num right label label-gray label-radius">43</span></a>
</li> -->
- {{if .IsRepositoryTrueOwner}}
+ {{if .IsRepositoryAdmin}}
<li class="border-bottom"></li>
<li>
<a class="radius" href="{{.RepoLink}}/settings"><i class="octicon octicon-tools"></i>{{.i18n.Tr "repo.settings"}}</a>
diff --git a/templates/repo/toolbar.tmpl b/templates/repo/toolbar.tmpl
index 6357b3c4c0..f2254d21dd 100644
--- a/templates/repo/toolbar.tmpl
+++ b/templates/repo/toolbar.tmpl
@@ -35,7 +35,7 @@
<li><a href="#">Pulse</a></li>
<li><a href="#">Network</a></li>
</ul>
- </li> -->{{end}}{{if .IsRepositoryTrueOwner}}
+ </li> -->{{end}}{{if .IsRepositoryAdmin}}
<li class="{{if .IsRepoToolbarSetting}}active{{end}}"><a href="{{.RepoLink}}/settings">Settings</a>
</li>{{end}}
</ul>
diff --git a/templates/user/auth/signin.tmpl b/templates/user/auth/signin.tmpl
index 78d6febb80..455df63ac8 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>&nbsp;&nbsp;&nbsp;&nbsp;
{{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/profile.tmpl b/templates/user/profile.tmpl
index fd33a40692..dab90c35a2 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>&nbsp;&nbsp;<a target="_blank" href="{{.Owner.Website}}">{{.Owner.Website}}</a></li>
{{end}}
- <li class="list-group-item"><i class="octicon octicon-clock"></i>&nbsp;&nbsp;{{.i18n.Tr "user.join_on"}} {{DateFormat .Owner.Created "M d, Y"}}</li>
+ <li class="list-group-item"><i class="octicon octicon-clock"></i>&nbsp;&nbsp;{{.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 ce74ef7766..2e766a3dc7 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 c99e6a0415..ec152c5d60 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 b47f883e51..f2a30da791 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 48a4d343ae..42b76039ee 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}}