Merge branch 'dev' of github.com:gogits/gogs into access

Conflicts:
	gogs.go
	models/models.go
	models/user.go
	templates/.VERSION
	templates/org/home.tmpl
This commit is contained in:
Unknwon 2015-02-22 22:51:25 -05:00
commit 7ccab9cd09
65 changed files with 477 additions and 462 deletions

View file

@ -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]

View file

@ -13,3 +13,4 @@ script: go build -v
notifications:
email:
- u@gogs.io
slack: gophercn:o5pSanyTeNhnfYc3QnG0X7Wx

View file

@ -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

View file

@ -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:

View file

@ -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")
})
})
})

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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=名前

View file

@ -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

View file

@ -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

View file

@ -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=Имя

View file

@ -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=发送者名称

View file

@ -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=發送者名稱

View file

@ -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

View file

@ -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

View file

@ -1,6 +1,6 @@
#!/bin/sh
if [ ! -d "$DIRECTORY" ]; then
if [ ! -d "$GOGS_CUSTOM_CONF_PATH" ]; then
mkdir -p $GOGS_CUSTOM_CONF_PATH
echo "

View file

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

View file

@ -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
}

View file

@ -16,7 +16,7 @@ import (
"github.com/go-xorm/xorm"
_ "github.com/lib/pq"
"github.com/gogits/gogs/models/migrations"
// "github.com/gogits/gogs/models/migrations"
"github.com/gogits/gogs/modules/setting"
)
@ -140,7 +140,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

View file

@ -103,7 +103,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 {

View file

@ -154,7 +154,6 @@ type Repository struct {
IsPrivate bool
IsBare bool
IsGoget bool
IsMirror bool
*Mirror `xorm:"-"`

View file

@ -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
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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,

View file

@ -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)
}

View file

@ -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
}

View file

@ -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 {

View file

@ -130,6 +130,18 @@ func (ctx *Context) Handle(status int, title string, err error) {
ctx.HTML(status, base.TplName(fmt.Sprintf("status/%d", status)))
}
func (ctx *Context) HandleAPI(status int, obj interface{}) {
var message string
if err, ok := obj.(error); ok {
message = err.Error()
} else {
message = obj.(string)
}
ctx.JSON(status, map[string]string{
"message": message,
})
}
func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
modtime := time.Now()
for _, p := range params {

View file

@ -317,8 +317,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)
}

View file

@ -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":

View file

@ -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;

View file

@ -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 selectTop = $select.offset().top;
var fromTop = $from.offset().top;
var hash;
var c;
if (a != b) {
if (a > b) {
c = a;
a = b;
b = c;
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);

View file

@ -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;

View file

@ -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

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -8,6 +8,7 @@ import (
"encoding/json"
"errors"
"fmt"
"path"
"strings"
"time"
@ -83,7 +84,6 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) {
ctx.Repo.Repository.Description = form.Description
ctx.Repo.Repository.Website = form.Website
ctx.Repo.Repository.IsPrivate = form.Private
ctx.Repo.Repository.IsGoget = form.GoGet
if err := models.UpdateRepository(ctx.Repo.Repository); err != nil {
ctx.Handle(404, "UpdateRepository", err)
return
@ -109,7 +109,7 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) {
}
newOwner := ctx.Query("new_owner_name")
isExist, err := models.IsUserExist(newOwner)
isExist, err := models.IsUserExist(0, newOwner)
if err != nil {
ctx.Handle(500, "IsUserExist", err)
return

View file

@ -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")

View file

@ -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)
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,
}
if err := models.AddEmailAddress(e); err != nil {
if err == models.ErrEmailAlreadyUsed {
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SETTINGS_EMAILS, &form)
return
}
ctx.Handle(500, "AddEmailAddress", err)
return
} else {
// Send confirmation e-mail
if setting.Service.RegisterEmailConfirm {
mailer.SendActivateEmail(ctx.Render, ctx.User, e)
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
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.Handle(500, "email.AddEmailAddress", err)
return
ctx.Flash.Success(ctx.Tr("settings.add_email_success_confirmation_email_sent"))
} 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"))
}
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"))
}
log.Trace("Email address added: %s", e.Email)
ctx.Redirect(setting.AppSubUrl + "/user/settings/email")
return
}
ctx.HTML(200, SETTINGS_EMAILS)

5
scripts/less.sh Executable file
View file

@ -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"

View file

@ -1 +1 @@
0.5.14.0213 Beta
0.5.14.0222 Beta

View file

@ -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}}

View file

@ -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>

View file

@ -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>

View file

@ -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}}

View file

@ -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}}

View file

@ -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" />

View file

@ -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">

View file

@ -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" .}}

View file

@ -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>

View file

@ -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" .}}

View file

@ -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/>

View file

@ -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">

View file

@ -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>

View file

@ -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>

View file

@ -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">

View file

@ -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">

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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}}