diff --git a/README.md b/README.md index 71e7a866e..f390f0836 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?branch=master)](https://travis-ci.org/gogits/gogs) [![Docker Repository on Quay](https://quay.io/repository/gogs/gogs/status "Docker Repository on Quay")](https://quay.io/repository/gogs/gogs) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/gogs/localized.svg)](https://crowdin.com/project/gogs) [![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 [![Build Status](https://travis-ci.org/gogits/gogs.svg?branch=master)](https://travis-ci.org/gogits/gogs) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/gogs/localized.svg)](https://crowdin.com/project/gogs) [![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) ===================== ![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true) -##### Current version: 0.8.45 +##### Current version: 0.8.46 | Web | UI | Preview | |:-------------:|:-------:|:-------:| @@ -11,15 +11,13 @@ Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?bra |![Profile](https://gogs.io/img/screenshots/4.png)|![Admin Dashboard](https://gogs.io/img/screenshots/5.png)|![Diff](https://gogs.io/img/screenshots/6.png)| |![Issues](https://gogs.io/img/screenshots/7.png)|![Releases](https://gogs.io/img/screenshots/8.png)|![Organization](https://gogs.io/img/screenshots/9.png)| -### NOTICES +### Important Notes -1. :bangbang: You **MUST** **MUST** **MUST** read [CONTRIBUTING.md](https://github.com/gogits/gogs/blob/master/.github/CONTRIBUTING.md) for bug report and contributing code. :bangbang: -2. **PLEASE** **PLEASE** **PLEASE** [ask questions](https://discuss.gogs.io/c/getting-help) on [the forum](https://discuss.gogs.io/). GitHub issue tracker only keeps **bugs** and **feature requests**, all other topics will be closed without reason. -3. Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) was reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site. -4. The demo site [try.gogs.io](https://try.gogs.io) is running under `develop` branch. -5. If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**. Thanks! -6. If you're interested in using APIs, we have experimental support with [documentation](https://github.com/gogits/go-gogs-client/wiki). -7. If your team/company is using Gogs and would like to put your logo on [our website](http://gogs.io), contact us by any means. +1. Due to testing purpose, data of [try.gogs.io](https://try.gogs.io) was reset in **Jan 28, 2015** and will reset multiple times after. Please do **NOT** put your important data on the site. +2. The demo site [try.gogs.io](https://try.gogs.io) is running under `develop` branch. +3. If you think there are vulnerabilities in the project, please talk privately to **u@gogs.io**. Thanks! +4. If you're interested in using APIs, we have experimental support with [documentation](https://github.com/gogits/go-gogs-client/wiki). +5. If your team/company is using Gogs and would like to put your logo on [our website](http://gogs.io), contact us by any means. [简体中文](README_ZH.md) @@ -32,7 +30,7 @@ The goal of this project is to make the easiest, fastest, and most painless way - Please see the [Documentation](http://gogs.io/docs/intro) for common usages 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/gogs/gogs)! -- Having trouble? Get help with [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.html). +- Having trouble? Get help with [Troubleshooting](http://gogs.io/docs/intro/troubleshooting.html) or [User Forum](https://discuss.gogs.io/). - Want to help with localization? Check out the [guide](http://gogs.io/docs/features/i18n.html)! ## Features diff --git a/README_ZH.md b/README_ZH.md index 27f930662..fddb4008d 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -12,7 +12,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自 - 有关基本用法和变更日志,请通过 [使用手册](http://gogs.io/docs/intro/) 查看。 - 您可以到 [Trello Board](https://trello.com/b/uxAoeLUl/gogs-go-git-service) 跟随开发团队的脚步。 - 想要先睹为快?直接去 [在线体验](https://try.gogs.io/gogs/gogs) 。 -- 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.html) 页面获取帮助。 +- 使用过程中遇到问题?尝试从 [故障排查](http://gogs.io/docs/intro/troubleshooting.html) 页面或 [用户论坛](https://discuss.gogs.io/) 获取帮助。 - 希望帮助多国语言界面的翻译吗?请立即访问 [详情页面](http://gogs.io/docs/features/i18n.html)! ## 功能特性 diff --git a/docker/README.md b/docker/README.md index bfdb4a60f..d4792208a 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,6 +1,6 @@ # Docker for Gogs -Visit [Docker Hub](https://hub.docker.com/r/gogs/gogs/) or [Quay](https://quay.io/repository/gogs/gogs) see all available tags. +Visit [Docker Hub](https://hub.docker.com/r/gogs/gogs/) see all available tags. ## Usage diff --git a/gogs.go b/gogs.go index 42b5fe1f9..fa8aba39f 100644 --- a/gogs.go +++ b/gogs.go @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.8.45.0225" +const APP_VER = "0.8.46.0227" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/issue.go b/models/issue.go index c9883a25e..94998d783 100644 --- a/models/issue.go +++ b/models/issue.go @@ -8,12 +8,10 @@ import ( "bytes" "errors" "fmt" - "html/template" "io" "mime/multipart" "os" "path" - "strconv" "strings" "time" @@ -936,233 +934,6 @@ func UpdateIssueUsersByMentions(uids []int64, iid int64) error { return nil } -// .____ ___. .__ -// | | _____ \_ |__ ____ | | -// | | \__ \ | __ \_/ __ \| | -// | |___ / __ \| \_\ \ ___/| |__ -// |_______ (____ /___ /\___ >____/ -// \/ \/ \/ \/ - -// Label represents a label of repository for issues. -type Label struct { - ID int64 `xorm:"pk autoincr"` - RepoID int64 `xorm:"INDEX"` - Name string - Color string `xorm:"VARCHAR(7)"` - NumIssues int - NumClosedIssues int - NumOpenIssues int `xorm:"-"` - IsChecked bool `xorm:"-"` -} - -// CalOpenIssues calculates the open issues of label. -func (m *Label) CalOpenIssues() { - m.NumOpenIssues = m.NumIssues - m.NumClosedIssues -} - -// ForegroundColor calculates the text color for labels based -// on their background color -func (l *Label) ForegroundColor() template.CSS { - if strings.HasPrefix(l.Color, "#") { - if color, err := strconv.ParseUint(l.Color[1:], 16, 64); err == nil { - r := float32(0xFF & (color >> 16)) - g := float32(0xFF & (color >> 8)) - b := float32(0xFF & color) - luminance := (0.2126*r + 0.7152*g + 0.0722*b) / 255 - - if luminance < 0.5 { - return template.CSS("rgba(255,255,255,.8)") - } - } - } - - // default to black - return template.CSS("rgba(0,0,0,.8)") -} - -// NewLabel creates new label of repository. -func NewLabel(l *Label) error { - _, err := x.Insert(l) - return err -} - -func getLabelByID(e Engine, id int64) (*Label, error) { - if id <= 0 { - return nil, ErrLabelNotExist{id} - } - - l := &Label{ID: id} - has, err := x.Get(l) - if err != nil { - return nil, err - } else if !has { - return nil, ErrLabelNotExist{l.ID} - } - return l, nil -} - -// GetLabelByID returns a label by given ID. -func GetLabelByID(id int64) (*Label, error) { - return getLabelByID(x, id) -} - -// GetLabelsByRepoID returns all labels that belong to given repository by ID. -func GetLabelsByRepoID(repoID int64) ([]*Label, error) { - labels := make([]*Label, 0, 10) - return labels, x.Where("repo_id=?", repoID).Find(&labels) -} - -func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) { - issueLabels, err := getIssueLabels(e, issueID) - if err != nil { - return nil, fmt.Errorf("getIssueLabels: %v", err) - } - - var label *Label - labels := make([]*Label, 0, len(issueLabels)) - for idx := range issueLabels { - label, err = getLabelByID(e, issueLabels[idx].LabelID) - if err != nil && !IsErrLabelNotExist(err) { - return nil, fmt.Errorf("getLabelByID: %v", err) - } - labels = append(labels, label) - } - return labels, nil -} - -// GetLabelsByIssueID returns all labels that belong to given issue by ID. -func GetLabelsByIssueID(issueID int64) ([]*Label, error) { - return getLabelsByIssueID(x, issueID) -} - -func updateLabel(e Engine, l *Label) error { - _, err := e.Id(l.ID).AllCols().Update(l) - return err -} - -// UpdateLabel updates label information. -func UpdateLabel(l *Label) error { - return updateLabel(x, l) -} - -// DeleteLabel delete a label of given repository. -func DeleteLabel(repoID, labelID int64) error { - l, err := GetLabelByID(labelID) - if err != nil { - if IsErrLabelNotExist(err) { - return nil - } - return err - } - - sess := x.NewSession() - defer sessionRelease(sess) - if err = sess.Begin(); err != nil { - return err - } - - if _, err = x.Where("label_id=?", labelID).Delete(new(IssueLabel)); err != nil { - return err - } else if _, err = sess.Delete(l); err != nil { - return err - } - return sess.Commit() -} - -// .___ .____ ___. .__ -// | | ______ ________ __ ____ | | _____ \_ |__ ____ | | -// | |/ ___// ___/ | \_/ __ \| | \__ \ | __ \_/ __ \| | -// | |\___ \ \___ \| | /\ ___/| |___ / __ \| \_\ \ ___/| |__ -// |___/____ >____ >____/ \___ >_______ (____ /___ /\___ >____/ -// \/ \/ \/ \/ \/ \/ \/ - -// IssueLabel represetns an issue-lable relation. -type IssueLabel struct { - ID int64 `xorm:"pk autoincr"` - IssueID int64 `xorm:"UNIQUE(s)"` - LabelID int64 `xorm:"UNIQUE(s)"` -} - -func hasIssueLabel(e Engine, issueID, labelID int64) bool { - has, _ := e.Where("issue_id=? AND label_id=?", issueID, labelID).Get(new(IssueLabel)) - return has -} - -// HasIssueLabel returns true if issue has been labeled. -func HasIssueLabel(issueID, labelID int64) bool { - return hasIssueLabel(x, issueID, labelID) -} - -func newIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) { - if _, err = e.Insert(&IssueLabel{ - IssueID: issue.ID, - LabelID: label.ID, - }); err != nil { - return err - } - - label.NumIssues++ - if issue.IsClosed { - label.NumClosedIssues++ - } - return updateLabel(e, label) -} - -// NewIssueLabel creates a new issue-label relation. -func NewIssueLabel(issue *Issue, label *Label) (err error) { - sess := x.NewSession() - defer sessionRelease(sess) - if err = sess.Begin(); err != nil { - return err - } - - if err = newIssueLabel(sess, issue, label); err != nil { - return err - } - - return sess.Commit() -} - -func getIssueLabels(e Engine, issueID int64) ([]*IssueLabel, error) { - issueLabels := make([]*IssueLabel, 0, 10) - return issueLabels, e.Where("issue_id=?", issueID).Asc("label_id").Find(&issueLabels) -} - -// GetIssueLabels returns all issue-label relations of given issue by ID. -func GetIssueLabels(issueID int64) ([]*IssueLabel, error) { - return getIssueLabels(x, issueID) -} - -func deleteIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) { - if _, err = e.Delete(&IssueLabel{ - IssueID: issue.ID, - LabelID: label.ID, - }); err != nil { - return err - } - - label.NumIssues-- - if issue.IsClosed { - label.NumClosedIssues-- - } - return updateLabel(e, label) -} - -// DeleteIssueLabel deletes issue-label relation. -func DeleteIssueLabel(issue *Issue, label *Label) (err error) { - sess := x.NewSession() - defer sessionRelease(sess) - if err = sess.Begin(); err != nil { - return err - } - - if err = deleteIssueLabel(sess, issue, label); err != nil { - return err - } - - return sess.Commit() -} - // _____ .__.__ __ // / \ |__| | ____ _______/ |_ ____ ____ ____ // / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \ diff --git a/models/issue_label.go b/models/issue_label.go new file mode 100644 index 000000000..4f814821f --- /dev/null +++ b/models/issue_label.go @@ -0,0 +1,234 @@ +// Copyright 2016 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package models + +import ( + "fmt" + "html/template" + "strconv" + "strings" + + "github.com/go-xorm/xorm" +) + +// Label represents a label of repository for issues. +type Label struct { + ID int64 `xorm:"pk autoincr"` + RepoID int64 `xorm:"INDEX"` + Name string + Color string `xorm:"VARCHAR(7)"` + NumIssues int + NumClosedIssues int + NumOpenIssues int `xorm:"-"` + IsChecked bool `xorm:"-"` +} + +// CalOpenIssues calculates the open issues of label. +func (m *Label) CalOpenIssues() { + m.NumOpenIssues = m.NumIssues - m.NumClosedIssues +} + +// ForegroundColor calculates the text color for labels based +// on their background color. +func (l *Label) ForegroundColor() template.CSS { + if strings.HasPrefix(l.Color, "#") { + if color, err := strconv.ParseUint(l.Color[1:], 16, 64); err == nil { + r := float32(0xFF & (color >> 16)) + g := float32(0xFF & (color >> 8)) + b := float32(0xFF & color) + luminance := (0.2126*r + 0.7152*g + 0.0722*b) / 255 + + if luminance < 0.5 { + return template.CSS("#fff") + } + } + } + + // default to black + return template.CSS("#000") +} + +// NewLabel creates new label of repository. +func NewLabel(l *Label) error { + _, err := x.Insert(l) + return err +} + +func getLabelByID(e Engine, id int64) (*Label, error) { + if id <= 0 { + return nil, ErrLabelNotExist{id} + } + + l := &Label{ID: id} + has, err := x.Get(l) + if err != nil { + return nil, err + } else if !has { + return nil, ErrLabelNotExist{l.ID} + } + return l, nil +} + +// GetLabelByID returns a label by given ID. +func GetLabelByID(id int64) (*Label, error) { + return getLabelByID(x, id) +} + +// GetLabelsByRepoID returns all labels that belong to given repository by ID. +func GetLabelsByRepoID(repoID int64) ([]*Label, error) { + labels := make([]*Label, 0, 10) + return labels, x.Where("repo_id=?", repoID).Find(&labels) +} + +func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) { + issueLabels, err := getIssueLabels(e, issueID) + if err != nil { + return nil, fmt.Errorf("getIssueLabels: %v", err) + } + + var label *Label + labels := make([]*Label, 0, len(issueLabels)) + for idx := range issueLabels { + label, err = getLabelByID(e, issueLabels[idx].LabelID) + if err != nil && !IsErrLabelNotExist(err) { + return nil, fmt.Errorf("getLabelByID: %v", err) + } + labels = append(labels, label) + } + return labels, nil +} + +// GetLabelsByIssueID returns all labels that belong to given issue by ID. +func GetLabelsByIssueID(issueID int64) ([]*Label, error) { + return getLabelsByIssueID(x, issueID) +} + +func updateLabel(e Engine, l *Label) error { + _, err := e.Id(l.ID).AllCols().Update(l) + return err +} + +// UpdateLabel updates label information. +func UpdateLabel(l *Label) error { + return updateLabel(x, l) +} + +// DeleteLabel delete a label of given repository. +func DeleteLabel(repoID, labelID int64) error { + l, err := GetLabelByID(labelID) + if err != nil { + if IsErrLabelNotExist(err) { + return nil + } + return err + } + + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + if _, err = x.Where("label_id=?", labelID).Delete(new(IssueLabel)); err != nil { + return err + } else if _, err = sess.Delete(l); err != nil { + return err + } + return sess.Commit() +} + +// .___ .____ ___. .__ +// | | ______ ________ __ ____ | | _____ \_ |__ ____ | | +// | |/ ___// ___/ | \_/ __ \| | \__ \ | __ \_/ __ \| | +// | |\___ \ \___ \| | /\ ___/| |___ / __ \| \_\ \ ___/| |__ +// |___/____ >____ >____/ \___ >_______ (____ /___ /\___ >____/ +// \/ \/ \/ \/ \/ \/ \/ + +// IssueLabel represetns an issue-lable relation. +type IssueLabel struct { + ID int64 `xorm:"pk autoincr"` + IssueID int64 `xorm:"UNIQUE(s)"` + LabelID int64 `xorm:"UNIQUE(s)"` +} + +func hasIssueLabel(e Engine, issueID, labelID int64) bool { + has, _ := e.Where("issue_id=? AND label_id=?", issueID, labelID).Get(new(IssueLabel)) + return has +} + +// HasIssueLabel returns true if issue has been labeled. +func HasIssueLabel(issueID, labelID int64) bool { + return hasIssueLabel(x, issueID, labelID) +} + +func newIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) { + if _, err = e.Insert(&IssueLabel{ + IssueID: issue.ID, + LabelID: label.ID, + }); err != nil { + return err + } + + label.NumIssues++ + if issue.IsClosed { + label.NumClosedIssues++ + } + return updateLabel(e, label) +} + +// NewIssueLabel creates a new issue-label relation. +func NewIssueLabel(issue *Issue, label *Label) (err error) { + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + if err = newIssueLabel(sess, issue, label); err != nil { + return err + } + + return sess.Commit() +} + +func getIssueLabels(e Engine, issueID int64) ([]*IssueLabel, error) { + issueLabels := make([]*IssueLabel, 0, 10) + return issueLabels, e.Where("issue_id=?", issueID).Asc("label_id").Find(&issueLabels) +} + +// GetIssueLabels returns all issue-label relations of given issue by ID. +func GetIssueLabels(issueID int64) ([]*IssueLabel, error) { + return getIssueLabels(x, issueID) +} + +func deleteIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) { + if _, err = e.Delete(&IssueLabel{ + IssueID: issue.ID, + LabelID: label.ID, + }); err != nil { + return err + } + + label.NumIssues-- + if issue.IsClosed { + label.NumClosedIssues-- + } + return updateLabel(e, label) +} + +// DeleteIssueLabel deletes issue-label relation. +func DeleteIssueLabel(issue *Issue, label *Label) (err error) { + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + if err = deleteIssueLabel(sess, issue, label); err != nil { + return err + } + + return sess.Commit() +} diff --git a/public/css/gogs.css b/public/css/gogs.css index 23da755aa..016ea7b96 100644 --- a/public/css/gogs.css +++ b/public/css/gogs.css @@ -1477,7 +1477,7 @@ footer .container .links > *:first-child { background-color: #fff; } .repository.view.issue .comment-list .comment .content > .bottom.segment a:before { - content: ""; + content: ' '; display: inline-block; height: 100%; vertical-align: middle; @@ -1601,6 +1601,9 @@ footer .container .links > *:first-child { .repository .label.list .item a.open-issues { margin-right: 30px; } +.repository .label.list .item .ui.label { + font-size: 1em; +} .repository .milestone.list { list-style: none; padding-top: 15px; diff --git a/public/less/_repository.less b/public/less/_repository.less index e6ad40af6..b1c2c8d7a 100644 --- a/public/less/_repository.less +++ b/public/less/_repository.less @@ -553,6 +553,9 @@ margin-right: 30px; } } + .ui.label { + font-size: 1em; + } } } diff --git a/templates/.VERSION b/templates/.VERSION index 748d3b702..d14247078 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.8.45.0225 \ No newline at end of file +0.8.46.0227 \ No newline at end of file