aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
Diffstat (limited to 'models')
-rw-r--r--models/action.go44
-rw-r--r--models/cron/cron.go59
-rw-r--r--models/git_diff.go6
-rw-r--r--models/issue.go259
-rw-r--r--models/issue_label.go234
-rw-r--r--models/login.go12
-rw-r--r--models/migrations/migrations.go2
-rw-r--r--models/org.go20
-rw-r--r--models/pull.go34
-rw-r--r--models/repo.go16
-rw-r--r--models/token.go5
-rw-r--r--models/update.go90
-rw-r--r--models/user.go5
-rw-r--r--models/webhook.go4
14 files changed, 407 insertions, 383 deletions
diff --git a/models/action.go b/models/action.go
index 3bcf999d..678d6c60 100644
--- a/models/action.go
+++ b/models/action.go
@@ -28,17 +28,19 @@ import (
type ActionType int
const (
- CREATE_REPO ActionType = iota + 1 // 1
- RENAME_REPO // 2
- STAR_REPO // 3
- FOLLOW_REPO // 4
- COMMIT_REPO // 5
- CREATE_ISSUE // 6
- CREATE_PULL_REQUEST // 7
- TRANSFER_REPO // 8
- PUSH_TAG // 9
- COMMENT_ISSUE // 10
- MERGE_PULL_REQUEST // 11
+ ACTION_CREATE_REPO ActionType = iota + 1 // 1
+ ACTION_RENAME_REPO // 2
+ ACTION_STAR_REPO // 3
+ ACTION_WATCH_REPO // 4
+ ACTION_COMMIT_REPO // 5
+ ACTION_CREATE_ISSUE // 6
+ ACTION_CREATE_PULL_REQUEST // 7
+ ACTION_TRANSFER_REPO // 8
+ ACTION_PUSH_TAG // 9
+ ACTION_COMMENT_ISSUE // 10
+ ACTION_MERGE_PULL_REQUEST // 11
+ ACTION_CLOSE_ISSUE // 12
+ ACTION_REOPEN_ISSUE // 13
)
var (
@@ -178,7 +180,7 @@ func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
ActUserID: u.Id,
ActUserName: u.Name,
ActEmail: u.Email,
- OpType: CREATE_REPO,
+ OpType: ACTION_CREATE_REPO,
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
RepoName: repo.Name,
@@ -201,7 +203,7 @@ func renameRepoAction(e Engine, actUser *User, oldRepoName string, repo *Reposit
ActUserID: actUser.Id,
ActUserName: actUser.Name,
ActEmail: actUser.Email,
- OpType: RENAME_REPO,
+ OpType: ACTION_RENAME_REPO,
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
RepoName: repo.Name,
@@ -366,7 +368,7 @@ func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string
continue
}
- if err = issue.ChangeStatus(u, true); err != nil {
+ if err = issue.ChangeStatus(u, repo, true); err != nil {
return err
}
}
@@ -406,7 +408,7 @@ func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string
continue
}
- if err = issue.ChangeStatus(u, false); err != nil {
+ if err = issue.ChangeStatus(u, repo, false); err != nil {
return err
}
}
@@ -443,10 +445,10 @@ func CommitRepoAction(
}
isNewBranch := false
- opType := COMMIT_REPO
+ opType := ACTION_COMMIT_REPO
// Check it's tag push or branch.
if strings.HasPrefix(refFullName, "refs/tags/") {
- opType = PUSH_TAG
+ opType = ACTION_PUSH_TAG
commit = &PushCommits{}
} else {
// if not the first commit, set the compareUrl
@@ -502,7 +504,7 @@ func CommitRepoAction(
}
switch opType {
- case COMMIT_REPO: // Push
+ case ACTION_COMMIT_REPO: // Push
p := &api.PushPayload{
Ref: refFullName,
Before: oldCommitID,
@@ -530,7 +532,7 @@ func CommitRepoAction(
})
}
- case PUSH_TAG: // Create
+ case ACTION_PUSH_TAG: // Create
return PrepareWebhooks(repo, HOOK_EVENT_CREATE, &api.CreatePayload{
Ref: refName,
RefType: "tag",
@@ -547,7 +549,7 @@ func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repos
ActUserID: actUser.Id,
ActUserName: actUser.Name,
ActEmail: actUser.Email,
- OpType: TRANSFER_REPO,
+ OpType: ACTION_TRANSFER_REPO,
RepoID: repo.ID,
RepoUserName: newOwner.Name,
RepoName: repo.Name,
@@ -578,7 +580,7 @@ func mergePullRequestAction(e Engine, actUser *User, repo *Repository, pull *Iss
ActUserID: actUser.Id,
ActUserName: actUser.Name,
ActEmail: actUser.Email,
- OpType: MERGE_PULL_REQUEST,
+ OpType: ACTION_MERGE_PULL_REQUEST,
Content: fmt.Sprintf("%d|%s", pull.Index, pull.Name),
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
diff --git a/models/cron/cron.go b/models/cron/cron.go
deleted file mode 100644
index 8e494e55..00000000
--- a/models/cron/cron.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package cron
-
-import (
- "time"
-
- "github.com/gogits/gogs/models"
- "github.com/gogits/gogs/modules/cron"
- "github.com/gogits/gogs/modules/log"
- "github.com/gogits/gogs/modules/setting"
-)
-
-var c = cron.New()
-
-func NewContext() {
- var (
- entry *cron.Entry
- err error
- )
- if setting.Cron.UpdateMirror.Enabled {
- entry, err = c.AddFunc("Update mirrors", setting.Cron.UpdateMirror.Schedule, models.MirrorUpdate)
- if err != nil {
- log.Fatal(4, "Cron[Update mirrors]: %v", err)
- }
- if setting.Cron.UpdateMirror.RunAtStart {
- entry.Prev = time.Now()
- go models.MirrorUpdate()
- }
- }
- if setting.Cron.RepoHealthCheck.Enabled {
- entry, err = c.AddFunc("Repository health check", setting.Cron.RepoHealthCheck.Schedule, models.GitFsck)
- if err != nil {
- log.Fatal(4, "Cron[Repository health check]: %v", err)
- }
- if setting.Cron.RepoHealthCheck.RunAtStart {
- entry.Prev = time.Now()
- go models.GitFsck()
- }
- }
- if setting.Cron.CheckRepoStats.Enabled {
- entry, err = c.AddFunc("Check repository statistics", setting.Cron.CheckRepoStats.Schedule, models.CheckRepoStats)
- if err != nil {
- log.Fatal(4, "Cron[Check repository statistics]: %v", err)
- }
- if setting.Cron.CheckRepoStats.RunAtStart {
- entry.Prev = time.Now()
- go models.CheckRepoStats()
- }
- }
- c.Start()
-}
-
-// ListTasks returns all running cron tasks.
-func ListTasks() []*cron.Entry {
- return c.Entries()
-}
diff --git a/models/git_diff.go b/models/git_diff.go
index 9796ef59..ab70139f 100644
--- a/models/git_diff.go
+++ b/models/git_diff.go
@@ -161,7 +161,6 @@ type DiffFile struct {
IsBin bool
IsRenamed bool
Sections []*DiffSection
- HighlightClass string
}
func (diffFile *DiffFile) GetType() int {
@@ -169,10 +168,7 @@ func (diffFile *DiffFile) GetType() int {
}
func (diffFile *DiffFile) GetHighlightClass() string {
- if diffFile.HighlightClass == "" {
- diffFile.HighlightClass = highlight.FileNameToHighlightClass(diffFile.Name)
- }
- return diffFile.HighlightClass
+ return highlight.FileNameToHighlightClass(diffFile.Name)
}
type Diff struct {
diff --git a/models/issue.go b/models/issue.go
index 32645463..94998d78 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -17,11 +17,11 @@ import (
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
+ gouuid "github.com/satori/go.uuid"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
- gouuid "github.com/gogits/gogs/modules/uuid"
)
var (
@@ -218,7 +218,7 @@ func (i *Issue) ReadBy(uid int64) error {
return UpdateIssueUserByRead(uid, i.ID)
}
-func (i *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (err error) {
+func (i *Issue) changeStatus(e *xorm.Session, doer *User, repo *Repository, isClosed bool) (err error) {
if i.IsClosed == isClosed {
return nil
}
@@ -251,7 +251,7 @@ func (i *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (err er
}
// New action comment.
- if _, err = createStatusComment(e, doer, i.Repo, i); err != nil {
+ if _, err = createStatusComment(e, doer, repo, i); err != nil {
return err
}
@@ -259,14 +259,14 @@ func (i *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (err er
}
// ChangeStatus changes issue status to open/closed.
-func (i *Issue) ChangeStatus(doer *User, isClosed bool) (err error) {
+func (i *Issue) ChangeStatus(doer *User, repo *Repository, isClosed bool) (err error) {
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
return err
}
- if err = i.changeStatus(sess, doer, isClosed); err != nil {
+ if err = i.changeStatus(sess, doer, repo, isClosed); err != nil {
return err
}
@@ -364,7 +364,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
ActUserID: issue.Poster.Id,
ActUserName: issue.Poster.Name,
ActEmail: issue.Poster.Email,
- OpType: CREATE_ISSUE,
+ OpType: ACTION_CREATE_ISSUE,
Content: fmt.Sprintf("%d|%s", issue.Index, issue.Name),
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
@@ -934,213 +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
-}
-
-// 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()
-}
-
// _____ .__.__ __
// / \ |__| | ____ _______/ |_ ____ ____ ____
// / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \
@@ -1564,9 +1357,24 @@ func createComment(e *xorm.Session, u *User, repo *Repository, issue *Issue, com
return nil, err
}
+ // Compose comment action, could be plain comment, close or reopen issue.
+ // This object will be used to notify watchers in the end of function.
+ act := &Action{
+ ActUserID: u.Id,
+ ActUserName: u.Name,
+ ActEmail: u.Email,
+ Content: fmt.Sprintf("%d|%s", issue.Index, strings.Split(content, "\n")[0]),
+ RepoID: repo.ID,
+ RepoUserName: repo.Owner.Name,
+ RepoName: repo.Name,
+ IsPrivate: repo.IsPrivate,
+ }
+
// Check comment type.
switch cmtType {
case COMMENT_TYPE_COMMENT:
+ act.OpType = ACTION_COMMENT_ISSUE
+
if _, err = e.Exec("UPDATE `issue` SET num_comments=num_comments+1 WHERE id=?", issue.ID); err != nil {
return nil, err
}
@@ -1593,23 +1401,9 @@ func createComment(e *xorm.Session, u *User, repo *Repository, issue *Issue, com
}
}
- // Notify watchers.
- act := &Action{
- ActUserID: u.Id,
- ActUserName: u.Name,
- ActEmail: u.Email,
- OpType: COMMENT_ISSUE,
- Content: fmt.Sprintf("%d|%s", issue.Index, strings.Split(content, "\n")[0]),
- RepoID: repo.ID,
- RepoUserName: repo.Owner.Name,
- RepoName: repo.Name,
- IsPrivate: repo.IsPrivate,
- }
- if err = notifyWatchers(e, act); err != nil {
- return nil, err
- }
-
case COMMENT_TYPE_REOPEN:
+ act.OpType = ACTION_REOPEN_ISSUE
+
if issue.IsPull {
_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls-1 WHERE id=?", repo.ID)
} else {
@@ -1619,6 +1413,8 @@ func createComment(e *xorm.Session, u *User, repo *Repository, issue *Issue, com
return nil, err
}
case COMMENT_TYPE_CLOSE:
+ act.OpType = ACTION_CLOSE_ISSUE
+
if issue.IsPull {
_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls+1 WHERE id=?", repo.ID)
} else {
@@ -1629,6 +1425,11 @@ func createComment(e *xorm.Session, u *User, repo *Repository, issue *Issue, com
}
}
+ // Notify watchers for whatever action comes in.
+ if err = notifyWatchers(e, act); err != nil {
+ return nil, fmt.Errorf("notifyWatchers: %v", err)
+ }
+
return comment, nil
}
diff --git a/models/issue_label.go b/models/issue_label.go
new file mode 100644
index 00000000..4f814821
--- /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/models/login.go b/models/login.go
index df890509..cbad646d 100644
--- a/models/login.go
+++ b/models/login.go
@@ -28,11 +28,11 @@ type LoginType int
// Note: new type must be added at the end of list to maintain compatibility.
const (
LOGIN_NOTYPE LoginType = iota
- LOGIN_PLAIN
- LOGIN_LDAP
- LOGIN_SMTP
- LOGIN_PAM
- LOGIN_DLDAP
+ LOGIN_PLAIN // 1
+ LOGIN_LDAP // 2
+ LOGIN_SMTP // 3
+ LOGIN_PAM // 4
+ LOGIN_DLDAP // 5
)
var (
@@ -42,7 +42,7 @@ var (
var LoginNames = map[LoginType]string{
LOGIN_LDAP: "LDAP (via BindDN)",
- LOGIN_DLDAP: "LDAP (simple auth)",
+ LOGIN_DLDAP: "LDAP (simple auth)", // Via direct bind
LOGIN_SMTP: "SMTP",
LOGIN_PAM: "PAM",
}
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 78729bde..c8e399e1 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -16,12 +16,12 @@ import (
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
+ gouuid "github.com/satori/go.uuid"
"gopkg.in/ini.v1"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
- gouuid "github.com/gogits/gogs/modules/uuid"
)
const _MIN_DB_VER = 4
diff --git a/models/org.go b/models/org.go
index de66af66..9d86df10 100644
--- a/models/org.go
+++ b/models/org.go
@@ -254,27 +254,25 @@ func IsPublicMembership(orgId, uid int64) bool {
return has
}
-func getOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) {
+func getOrgsByUserID(sess *xorm.Session, userID int64, showAll bool) ([]*User, error) {
orgs := make([]*User, 0, 10)
- return orgs, sess.Where("`org_user`.uid=?", userID).
+ if !showAll {
+ sess.And("`org_user`.is_public=?", true)
+ }
+ return orgs, sess.And("`org_user`.uid=?", userID).
Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id").Find(&orgs)
}
// GetOrgsByUserID returns a list of organizations that the given user ID
// has joined.
-func GetOrgsByUserID(userID int64) ([]*User, error) {
- sess := x.NewSession()
- return getOrgsByUserID(sess, userID)
+func GetOrgsByUserID(userID int64, showAll bool) ([]*User, error) {
+ return getOrgsByUserID(x.NewSession(), userID, showAll)
}
// GetOrgsByUserIDDesc returns a list of organizations that the given user ID
// has joined, ordered descending by the given condition.
-func GetOrgsByUserIDDesc(userID int64, desc string, all bool) ([]*User, error) {
- sess := x.NewSession()
- if !all {
- sess.And("`org_user`.is_public=?", true)
- }
- return getOrgsByUserID(sess.Desc(desc), userID)
+func GetOrgsByUserIDDesc(userID int64, desc string, showAll bool) ([]*User, error) {
+ return getOrgsByUserID(x.NewSession().Desc(desc), userID, showAll)
}
func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) {
diff --git a/models/pull.go b/models/pull.go
index 330319f9..276dc1bc 100644
--- a/models/pull.go
+++ b/models/pull.go
@@ -138,7 +138,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
return err
}
- if err = pr.Issue.changeStatus(sess, doer, true); err != nil {
+ if err = pr.Issue.changeStatus(sess, doer, pr.Issue.Repo, true); err != nil {
return fmt.Errorf("Issue.changeStatus: %v", err)
}
@@ -330,7 +330,7 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
ActUserID: pull.Poster.Id,
ActUserName: pull.Poster.Name,
ActEmail: pull.Poster.Email,
- OpType: CREATE_PULL_REQUEST,
+ OpType: ACTION_CREATE_PULL_REQUEST,
Content: fmt.Sprintf("%d|%s", pull.Index, pull.Name),
RepoID: repo.ID,
RepoUserName: repo.Owner.Name,
@@ -482,6 +482,33 @@ func (pr *PullRequest) UpdatePatch() (err error) {
return nil
}
+// PushToBaseRepo pushes commits from branches of head repository to
+// corresponding branches of base repository.
+// FIXME: could fail after user force push head repo, should we always force push here?
+// FIXME: Only push branches that are actually updates?
+func (pr *PullRequest) PushToBaseRepo() (err error) {
+ log.Trace("PushToBaseRepo[%[1]d]: pushing commits to base repo 'refs/pull/%[1]d/head'", pr.ID)
+
+ headRepoPath := pr.HeadRepo.RepoPath()
+ headGitRepo, err := git.OpenRepository(headRepoPath)
+ if err != nil {
+ return fmt.Errorf("OpenRepository: %v", err)
+ }
+
+ tmpRemoteName := fmt.Sprintf("tmp-pull-%d", pr.ID)
+ if err = headGitRepo.AddRemote(tmpRemoteName, pr.BaseRepo.RepoPath(), false); err != nil {
+ return fmt.Errorf("headGitRepo.AddRemote: %v", err)
+ }
+ // Make sure to remove the remote even if the push fails
+ defer headGitRepo.RemoveRemote(tmpRemoteName)
+
+ if err = git.Push(headRepoPath, tmpRemoteName, fmt.Sprintf("%s:refs/pull/%d/head", pr.HeadBranch, pr.Index)); err != nil {
+ return fmt.Errorf("Push: %v", err)
+ }
+
+ return nil
+}
+
// AddToTaskQueue adds itself to pull request test task queue.
func (pr *PullRequest) AddToTaskQueue() {
go PullRequestQueue.AddFunc(pr.ID, func() {
@@ -498,6 +525,9 @@ func addHeadRepoTasks(prs []*PullRequest) {
if err := pr.UpdatePatch(); err != nil {
log.Error(4, "UpdatePatch: %v", err)
continue
+ } else if err := pr.PushToBaseRepo(); err != nil {
+ log.Error(4, "PushToBaseRepo: %v", err)
+ continue
}
pr.AddToTaskQueue()
diff --git a/models/repo.go b/models/repo.go
index 57014beb..089a5998 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -30,9 +30,9 @@ import (
"github.com/gogits/git-module"
api "github.com/gogits/go-gogs-client"
- "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/bindata"
"github.com/gogits/gogs/modules/log"
+ "github.com/gogits/gogs/modules/markdown"
"github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
)
@@ -332,7 +332,17 @@ func (repo *Repository) IsOwnedBy(userID int64) bool {
// CanBeForked returns true if repository meets the requirements of being forked.
func (repo *Repository) CanBeForked() bool {
- return !repo.IsBare && !repo.IsMirror
+ return !repo.IsBare
+}
+
+// CanEnablePulls returns true if repository meets the requirements of accepting pulls.
+func (repo *Repository) CanEnablePulls() bool {
+ return !repo.IsMirror
+}
+
+// AllowPulls returns true if repository meets the requirements of accepting pulls and has them enabled.
+func (repo *Repository) AllowsPulls() bool {
+ return repo.CanEnablePulls() && repo.EnablePulls
}
func (repo *Repository) NextIssueIndex() int64 {
@@ -348,7 +358,7 @@ func (repo *Repository) DescriptionHtml() template.HTML {
sanitize := func(s string) string {
return fmt.Sprintf(`<a href="%[1]s" target="_blank">%[1]s</a>`, s)
}
- return template.HTML(DescPattern.ReplaceAllStringFunc(base.Sanitizer.Sanitize(repo.Description), sanitize))
+ return template.HTML(DescPattern.ReplaceAllStringFunc(markdown.Sanitizer.Sanitize(repo.Description), sanitize))
}
func (repo *Repository) LocalCopyPath() string {
diff --git a/models/token.go b/models/token.go
index 136753c3..adf50a43 100644
--- a/models/token.go
+++ b/models/token.go
@@ -7,8 +7,9 @@ package models
import (
"time"
+ gouuid "github.com/satori/go.uuid"
+
"github.com/gogits/gogs/modules/base"
- "github.com/gogits/gogs/modules/uuid"
)
// AccessToken represents a personal access token.
@@ -25,7 +26,7 @@ type AccessToken struct {
// NewAccessToken creates new access token.
func NewAccessToken(t *AccessToken) error {
- t.Sha1 = base.EncodeSha1(uuid.NewV4().String())
+ t.Sha1 = base.EncodeSha1(gouuid.NewV4().String())
_, err := x.Insert(t)
return err
}
diff --git a/models/update.go b/models/update.go
index 5c6ea7f6..66775ea9 100644
--- a/models/update.go
+++ b/models/update.go
@@ -10,7 +10,7 @@ import (
"os/exec"
"strings"
- "github.com/gogits/git-module"
+ git "github.com/gogits/git-module"
"github.com/gogits/gogs/modules/log"
)
@@ -65,94 +65,104 @@ func ListToPushCommits(l *list.List) *PushCommits {
return &PushCommits{l.Len(), commits, "", nil}
}
-func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName string, userID int64) error {
- isNew := strings.HasPrefix(oldCommitID, "0000000")
- if isNew &&
- strings.HasPrefix(newCommitID, "0000000") {
- return fmt.Errorf("old rev and new rev both 000000")
+type PushUpdateOptions struct {
+ RefName string
+ OldCommitID string
+ NewCommitID string
+ PusherID int64
+ PusherName string
+ RepoUserName string
+ RepoName string
+}
+
+// PushUpdate must be called for any push actions in order to
+// generates necessary push action history feeds.
+func PushUpdate(opts PushUpdateOptions) (err error) {
+ isNewRef := strings.HasPrefix(opts.OldCommitID, "0000000")
+ isDelRef := strings.HasPrefix(opts.NewCommitID, "0000000")
+ if isNewRef && isDelRef {
+ return fmt.Errorf("Old and new revisions both start with 000000")
}
- f := RepoPath(repoUserName, repoName)
+ repoPath := RepoPath(opts.RepoUserName, opts.RepoName)
gitUpdate := exec.Command("git", "update-server-info")
- gitUpdate.Dir = f
- gitUpdate.Run()
+ gitUpdate.Dir = repoPath
+ if err = gitUpdate.Run(); err != nil {
+ return fmt.Errorf("Fail to call 'git update-server-info': %v", err)
+ }
- isDel := strings.HasPrefix(newCommitID, "0000000")
- if isDel {
- log.GitLogger.Info("del rev", refName, "from", userName+"/"+repoName+".git", "by", userID)
+ if isDelRef {
+ log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %d",
+ opts.RefName, opts.RepoUserName, opts.RepoName, opts.PusherName)
return nil
}
- gitRepo, err := git.OpenRepository(f)
+ gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
- return fmt.Errorf("runUpdate.Open repoId: %v", err)
+ return fmt.Errorf("OpenRepository: %v", err)
}
- user, err := GetUserByName(repoUserName)
+ repoUser, err := GetUserByName(opts.RepoUserName)
if err != nil {
- return fmt.Errorf("runUpdate.GetUserByName: %v", err)
+ return fmt.Errorf("GetUserByName: %v", err)
}
- repo, err := GetRepositoryByName(user.Id, repoName)
+ repo, err := GetRepositoryByName(repoUser.Id, opts.RepoName)
if err != nil {
- return fmt.Errorf("runUpdate.GetRepositoryByName userId: %v", err)
+ return fmt.Errorf("GetRepositoryByName: %v", err)
}
// Push tags.
- if strings.HasPrefix(refName, "refs/tags/") {
- tagName := git.RefEndName(refName)
- tag, err := gitRepo.GetTag(tagName)
+ if strings.HasPrefix(opts.RefName, "refs/tags/") {
+ tag, err := gitRepo.GetTag(git.RefEndName(opts.RefName))
if err != nil {
- log.GitLogger.Fatal(4, "runUpdate.GetTag: %v", err)
+ return fmt.Errorf("gitRepo.GetTag: %v", err)
}
+ // When tagger isn't available, fall back to get committer email.
var actEmail string
if tag.Tagger != nil {
actEmail = tag.Tagger.Email
} else {
cmt, err := tag.Commit()
if err != nil {
- log.GitLogger.Fatal(4, "runUpdate.GetTag Commit: %v", err)
+ return fmt.Errorf("tag.Commit: %v", err)
}
actEmail = cmt.Committer.Email
}
commit := &PushCommits{}
-
- if err = CommitRepoAction(userID, user.Id, userName, actEmail,
- repo.ID, repoUserName, repoName, refName, commit, oldCommitID, newCommitID); err != nil {
- log.GitLogger.Fatal(4, "CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
+ if err = CommitRepoAction(opts.PusherID, repoUser.Id, opts.PusherName, actEmail,
+ repo.ID, opts.RepoUserName, opts.RepoName, opts.RefName, commit, opts.OldCommitID, opts.NewCommitID); err != nil {
+ return fmt.Errorf("CommitRepoAction (tag): %v", err)
}
return err
}
- newCommit, err := gitRepo.GetCommit(newCommitID)
+ newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
if err != nil {
- return fmt.Errorf("runUpdate GetCommit of newCommitId: %v", err)
+ return fmt.Errorf("gitRepo.GetCommit: %v", err)
}
// Push new branch.
var l *list.List
- if isNew {
+ if isNewRef {
l, err = newCommit.CommitsBeforeLimit(10)
if err != nil {
- return fmt.Errorf("CommitsBefore: %v", err)
+ return fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err)
}
} else {
- l, err = newCommit.CommitsBeforeUntil(oldCommitID)
+ l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
if err != nil {
- return fmt.Errorf("CommitsBeforeUntil: %v", err)
+ return fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err)
}
}
- if err != nil {
- return fmt.Errorf("runUpdate.Commit repoId: %v", err)
- }
-
- if err = CommitRepoAction(userID, user.Id, userName, user.Email,
- repo.ID, repoUserName, repoName, refName, ListToPushCommits(l), oldCommitID, newCommitID); err != nil {
- return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
+ if err = CommitRepoAction(opts.PusherID, repoUser.Id, opts.PusherName, repoUser.Email,
+ repo.ID, opts.RepoUserName, opts.RepoName, opts.RefName, ListToPushCommits(l),
+ opts.OldCommitID, opts.NewCommitID); err != nil {
+ return fmt.Errorf("CommitRepoAction (branch): %v", err)
}
return nil
}
diff --git a/models/user.go b/models/user.go
index 7a881759..3264c063 100644
--- a/models/user.go
+++ b/models/user.go
@@ -29,6 +29,7 @@ import (
"github.com/gogits/gogs/modules/avatar"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
+ "github.com/gogits/gogs/modules/markdown"
"github.com/gogits/gogs/modules/setting"
)
@@ -111,7 +112,7 @@ func (u *User) BeforeUpdate() {
func (u *User) AfterSet(colName string, _ xorm.Cell) {
switch colName {
case "full_name":
- u.FullName = base.Sanitizer.Sanitize(u.FullName)
+ u.FullName = markdown.Sanitizer.Sanitize(u.FullName)
case "created":
u.Created = regulateTimeZone(u.Created)
}
@@ -641,7 +642,7 @@ func updateUser(e Engine, u *User) error {
u.Description = u.Description[:255]
}
- u.FullName = base.Sanitizer.Sanitize(u.FullName)
+ u.FullName = markdown.Sanitizer.Sanitize(u.FullName)
_, err := e.Id(u.Id).AllCols().Update(u)
return err
}
diff --git a/models/webhook.go b/models/webhook.go
index bdfb62d8..c20a72e9 100644
--- a/models/webhook.go
+++ b/models/webhook.go
@@ -15,13 +15,13 @@ import (
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
+ gouuid "github.com/satori/go.uuid"
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/modules/httplib"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
- "github.com/gogits/gogs/modules/uuid"
)
type HookContentType int
@@ -361,7 +361,7 @@ func CreateHookTask(t *HookTask) error {
if err != nil {
return err
}
- t.UUID = uuid.NewV4().String()
+ t.UUID = gouuid.NewV4().String()
t.PayloadContent = string(data)
_, err = x.Insert(t)
return err