aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
Diffstat (limited to 'models')
-rw-r--r--models/access.go25
-rw-r--r--models/action.go39
-rw-r--r--models/fix.go6
-rw-r--r--models/git_diff.go13
-rw-r--r--models/issue.go90
-rw-r--r--models/login.go107
-rw-r--r--models/models.go55
-rw-r--r--models/oauth2.go32
-rw-r--r--models/org.go236
-rw-r--r--models/publickey.go36
-rw-r--r--models/release.go121
-rw-r--r--models/repo.go472
-rw-r--r--models/update.go31
-rw-r--r--models/user.go221
-rw-r--r--models/webhook.go143
15 files changed, 1074 insertions, 553 deletions
diff --git a/models/access.go b/models/access.go
index 4a202dc6..5238daba 100644
--- a/models/access.go
+++ b/models/access.go
@@ -11,26 +11,27 @@ import (
"github.com/go-xorm/xorm"
)
-// Access types.
+type AccessType int
+
const (
- AU_READABLE = iota + 1
- AU_WRITABLE
+ READABLE AccessType = iota + 1
+ WRITABLE
)
// Access represents the accessibility of user to repository.
type Access struct {
Id int64
- UserName string `xorm:"unique(s)"`
- RepoName string `xorm:"unique(s)"` // <user name>/<repo name>
- Mode int `xorm:"unique(s)"`
- Created time.Time `xorm:"created"`
+ UserName string `xorm:"unique(s)"`
+ RepoName string `xorm:"unique(s)"` // <user name>/<repo name>
+ Mode AccessType `xorm:"unique(s)"`
+ Created time.Time `xorm:"created"`
}
// AddAccess adds new access record.
func AddAccess(access *Access) error {
access.UserName = strings.ToLower(access.UserName)
access.RepoName = strings.ToLower(access.RepoName)
- _, err := orm.Insert(access)
+ _, err := x.Insert(access)
return err
}
@@ -38,13 +39,13 @@ func AddAccess(access *Access) error {
func UpdateAccess(access *Access) error {
access.UserName = strings.ToLower(access.UserName)
access.RepoName = strings.ToLower(access.RepoName)
- _, err := orm.Id(access.Id).Update(access)
+ _, err := x.Id(access.Id).Update(access)
return err
}
// DeleteAccess deletes access record.
func DeleteAccess(access *Access) error {
- _, err := orm.Delete(access)
+ _, err := x.Delete(access)
return err
}
@@ -59,7 +60,7 @@ func UpdateAccessWithSession(sess *xorm.Session, access *Access) error {
// HasAccess returns true if someone can read or write to given repository.
// The repoName should be in format <username>/<reponame>.
-func HasAccess(uname, repoName string, mode int) (bool, error) {
+func HasAccess(uname, repoName string, mode AccessType) (bool, error) {
if len(repoName) == 0 {
return false, nil
}
@@ -67,7 +68,7 @@ func HasAccess(uname, repoName string, mode int) (bool, error) {
UserName: strings.ToLower(uname),
RepoName: strings.ToLower(repoName),
}
- has, err := orm.Get(access)
+ has, err := x.Get(access)
if err != nil {
return false, err
} else if !has {
diff --git a/models/action.go b/models/action.go
index 9fc9d89b..55557da2 100644
--- a/models/action.go
+++ b/models/action.go
@@ -12,10 +12,8 @@ import (
"time"
"github.com/gogits/git"
- qlog "github.com/qiniu/log"
"github.com/gogits/gogs/modules/base"
- "github.com/gogits/gogs/modules/hooks"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/setting"
)
@@ -116,7 +114,7 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
return errors.New("action.CommitRepoAction(NotifyWatchers): " + err.Error())
}
- qlog.Info("action.CommitRepoAction(end): %d/%s", repoUserId, repoName)
+ //qlog.Info("action.CommitRepoAction(end): %d/%s", repoUserId, repoName)
// New push event hook.
if err := repo.GetOwner(); err != nil {
@@ -131,35 +129,35 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
}
repoLink := fmt.Sprintf("%s%s/%s", setting.AppUrl, repoUserName, repoName)
- commits := make([]*hooks.PayloadCommit, len(commit.Commits))
+ commits := make([]*PayloadCommit, len(commit.Commits))
for i, cmt := range commit.Commits {
- commits[i] = &hooks.PayloadCommit{
+ commits[i] = &PayloadCommit{
Id: cmt.Sha1,
Message: cmt.Message,
Url: fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1),
- Author: &hooks.PayloadAuthor{
+ Author: &PayloadAuthor{
Name: cmt.AuthorName,
Email: cmt.AuthorEmail,
},
}
}
- p := &hooks.Payload{
+ p := &Payload{
Ref: refFullName,
Commits: commits,
- Repo: &hooks.PayloadRepo{
+ Repo: &PayloadRepo{
Id: repo.Id,
Name: repo.LowerName,
Url: repoLink,
Description: repo.Description,
Website: repo.Website,
Watchers: repo.NumWatches,
- Owner: &hooks.PayloadAuthor{
+ Owner: &PayloadAuthor{
Name: repoUserName,
Email: actEmail,
},
Private: repo.IsPrivate,
},
- Pusher: &hooks.PayloadAuthor{
+ Pusher: &PayloadAuthor{
Name: repo.Owner.LowerName,
Email: repo.Owner.Email,
},
@@ -172,20 +170,27 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string,
}
p.Secret = w.Secret
- hooks.AddHookTask(&hooks.HookTask{hooks.HTT_WEBHOOK, w.Url, p, w.ContentType, w.IsSsl})
+ CreateHookTask(&HookTask{
+ Type: WEBHOOK,
+ Url: w.Url,
+ Payload: p,
+ ContentType: w.ContentType,
+ IsSsl: w.IsSsl,
+ })
}
return nil
}
// NewRepoAction adds new action for creating repository.
-func NewRepoAction(user *User, repo *Repository) (err error) {
- if err = NotifyWatchers(&Action{ActUserId: user.Id, ActUserName: user.Name, ActEmail: user.Email,
- OpType: OP_CREATE_REPO, RepoId: repo.Id, RepoName: repo.Name, IsPrivate: repo.IsPrivate}); err != nil {
- log.Error("action.NewRepoAction(notify watchers): %d/%s", user.Id, repo.Name)
+func NewRepoAction(u *User, repo *Repository) (err error) {
+ if err = NotifyWatchers(&Action{ActUserId: u.Id, ActUserName: u.Name, ActEmail: u.Email,
+ OpType: OP_CREATE_REPO, RepoId: repo.Id, RepoUserName: repo.Owner.Name, RepoName: repo.Name,
+ IsPrivate: repo.IsPrivate}); err != nil {
+ log.Error("action.NewRepoAction(notify watchers): %d/%s", u.Id, repo.Name)
return err
}
- log.Trace("action.NewRepoAction: %s/%s", user.LowerName, repo.LowerName)
+ log.Trace("action.NewRepoAction: %s/%s", u.LowerName, repo.LowerName)
return err
}
@@ -205,7 +210,7 @@ func TransferRepoAction(user, newUser *User, repo *Repository) (err error) {
// GetFeeds returns action list of given user in given context.
func GetFeeds(userid, offset int64, isProfile bool) ([]*Action, error) {
actions := make([]*Action, 0, 20)
- sess := orm.Limit(20, int(offset)).Desc("id").Where("user_id=?", userid)
+ sess := x.Limit(20, int(offset)).Desc("id").Where("user_id=?", userid)
if isProfile {
sess.Where("is_private=?", false).And("act_user_id=?", userid)
} else {
diff --git a/models/fix.go b/models/fix.go
deleted file mode 100644
index 9fc141bd..00000000
--- a/models/fix.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package models
-
-func Fix() error {
- _, err := orm.Exec("alter table repository drop column num_releases")
- return err
-}
diff --git a/models/git_diff.go b/models/git_diff.go
index 5b5a46a1..ed114b75 100644
--- a/models/git_diff.go
+++ b/models/git_diff.go
@@ -6,6 +6,7 @@ package models
import (
"bufio"
+ "fmt"
"io"
"os"
"os/exec"
@@ -15,6 +16,7 @@ import (
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
+ "github.com/gogits/gogs/modules/process"
)
// Diff line types.
@@ -67,7 +69,7 @@ func (diff *Diff) NumFiles() int {
const DIFF_HEAD = "diff --git "
-func ParsePatch(cmd *exec.Cmd, reader io.Reader) (*Diff, error) {
+func ParsePatch(pid int64, cmd *exec.Cmd, reader io.Reader) (*Diff, error) {
scanner := bufio.NewScanner(reader)
var (
curFile *DiffFile
@@ -169,11 +171,8 @@ func ParsePatch(cmd *exec.Cmd, reader io.Reader) (*Diff, error) {
}
// In case process became zombie.
- if !cmd.ProcessState.Exited() {
- log.Debug("git_diff.ParsePatch: process doesn't exit and now will be killed")
- if err := cmd.Process.Kill(); err != nil {
- log.Error("git_diff.ParsePatch: fail to kill zombie process: %v", err)
- }
+ if err := process.Kill(pid); err != nil {
+ log.Error("git_diff.ParsePatch(Kill): %v", err)
}
return diff, nil
}
@@ -207,5 +206,5 @@ func GetDiff(repoPath, commitid string) (*Diff, error) {
wr.Close()
}()
defer rd.Close()
- return ParsePatch(cmd, rd)
+ return ParsePatch(process.Add(fmt.Sprintf("GetDiff(%s)", repoPath), cmd), cmd, rd)
}
diff --git a/models/issue.go b/models/issue.go
index 18057985..6d67a72b 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -92,7 +92,7 @@ func (i *Issue) GetAssignee() (err error) {
// CreateIssue creates new issue for repository.
func NewIssue(issue *Issue) (err error) {
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
@@ -114,7 +114,7 @@ func NewIssue(issue *Issue) (err error) {
// GetIssueByIndex returns issue by given index in repository.
func GetIssueByIndex(rid, index int64) (*Issue, error) {
issue := &Issue{RepoId: rid, Index: index}
- has, err := orm.Get(issue)
+ has, err := x.Get(issue)
if err != nil {
return nil, err
} else if !has {
@@ -126,7 +126,7 @@ func GetIssueByIndex(rid, index int64) (*Issue, error) {
// GetIssueById returns an issue by ID.
func GetIssueById(id int64) (*Issue, error) {
issue := &Issue{Id: id}
- has, err := orm.Get(issue)
+ has, err := x.Get(issue)
if err != nil {
return nil, err
} else if !has {
@@ -137,7 +137,7 @@ func GetIssueById(id int64) (*Issue, error) {
// GetIssues returns a list of issues by given conditions.
func GetIssues(uid, rid, pid, mid int64, page int, isClosed bool, labelIds, sortType string) ([]Issue, error) {
- sess := orm.Limit(20, (page-1)*20)
+ sess := x.Limit(20, (page-1)*20)
if rid > 0 {
sess.Where("repo_id=?", rid).And("is_closed=?", isClosed)
@@ -193,13 +193,13 @@ const (
// GetIssuesByLabel returns a list of issues by given label and repository.
func GetIssuesByLabel(repoId int64, label string) ([]*Issue, error) {
issues := make([]*Issue, 0, 10)
- err := orm.Where("repo_id=?", repoId).And("label_ids like '%$" + label + "|%'").Find(&issues)
+ err := x.Where("repo_id=?", repoId).And("label_ids like '%$" + label + "|%'").Find(&issues)
return issues, err
}
// GetIssueCountByPoster returns number of issues of repository by poster.
func GetIssueCountByPoster(uid, rid int64, isClosed bool) int64 {
- count, _ := orm.Where("repo_id=?", rid).And("poster_id=?", uid).And("is_closed=?", isClosed).Count(new(Issue))
+ count, _ := x.Where("repo_id=?", rid).And("poster_id=?", uid).And("is_closed=?", isClosed).Count(new(Issue))
return count
}
@@ -213,9 +213,9 @@ func GetIssueCountByPoster(uid, rid int64, isClosed bool) int64 {
// IssueUser represents an issue-user relation.
type IssueUser struct {
Id int64
- Uid int64 // User ID.
+ Uid int64 `xorm:"INDEX"` // User ID.
IssueId int64
- RepoId int64
+ RepoId int64 `xorm:"INDEX"`
MilestoneId int64
IsRead bool
IsAssigned bool
@@ -241,7 +241,7 @@ func NewIssueUserPairs(rid, iid, oid, pid, aid int64, repoName string) (err erro
isNeedAddPoster = false
}
iu.IsAssigned = iu.Uid == aid
- if _, err = orm.Insert(iu); err != nil {
+ if _, err = x.Insert(iu); err != nil {
return err
}
}
@@ -249,7 +249,7 @@ func NewIssueUserPairs(rid, iid, oid, pid, aid int64, repoName string) (err erro
iu.Uid = pid
iu.IsPoster = true
iu.IsAssigned = iu.Uid == aid
- if _, err = orm.Insert(iu); err != nil {
+ if _, err = x.Insert(iu); err != nil {
return err
}
}
@@ -270,7 +270,7 @@ func PairsContains(ius []*IssueUser, issueId int64) int {
// GetIssueUserPairs returns issue-user pairs by given repository and user.
func GetIssueUserPairs(rid, uid int64, isClosed bool) ([]*IssueUser, error) {
ius := make([]*IssueUser, 0, 10)
- err := orm.Where("is_closed=?", isClosed).Find(&ius, &IssueUser{RepoId: rid, Uid: uid})
+ err := x.Where("is_closed=?", isClosed).Find(&ius, &IssueUser{RepoId: rid, Uid: uid})
return ius, err
}
@@ -285,7 +285,7 @@ func GetIssueUserPairsByRepoIds(rids []int64, isClosed bool, page int) ([]*Issue
cond := strings.TrimSuffix(buf.String(), " OR ")
ius := make([]*IssueUser, 0, 10)
- sess := orm.Limit(20, (page-1)*20).Where("is_closed=?", isClosed)
+ sess := x.Limit(20, (page-1)*20).Where("is_closed=?", isClosed)
if len(cond) > 0 {
sess.And(cond)
}
@@ -296,7 +296,7 @@ func GetIssueUserPairsByRepoIds(rids []int64, isClosed bool, page int) ([]*Issue
// GetIssueUserPairsByMode returns issue-user pairs by given repository and user.
func GetIssueUserPairsByMode(uid, rid int64, isClosed bool, page, filterMode int) ([]*IssueUser, error) {
ius := make([]*IssueUser, 0, 10)
- sess := orm.Limit(20, (page-1)*20).Where("uid=?", uid).And("is_closed=?", isClosed)
+ sess := x.Limit(20, (page-1)*20).Where("uid=?", uid).And("is_closed=?", isClosed)
if rid > 0 {
sess.And("repo_id=?", rid)
}
@@ -335,7 +335,7 @@ func GetIssueStats(rid, uid int64, isShowClosed bool, filterMode int) *IssueStat
issue := new(Issue)
tmpSess := &xorm.Session{}
- sess := orm.Where("repo_id=?", rid)
+ sess := x.Where("repo_id=?", rid)
*tmpSess = *sess
stats.OpenCount, _ = tmpSess.And("is_closed=?", false).Count(issue)
*tmpSess = *sess
@@ -347,7 +347,7 @@ func GetIssueStats(rid, uid int64, isShowClosed bool, filterMode int) *IssueStat
}
if filterMode != FM_MENTION {
- sess = orm.Where("repo_id=?", rid)
+ sess = x.Where("repo_id=?", rid)
switch filterMode {
case FM_ASSIGN:
sess.And("assignee_id=?", uid)
@@ -361,16 +361,16 @@ func GetIssueStats(rid, uid int64, isShowClosed bool, filterMode int) *IssueStat
*tmpSess = *sess
stats.ClosedCount, _ = tmpSess.And("is_closed=?", true).Count(issue)
} else {
- sess := orm.Where("repo_id=?", rid).And("uid=?", uid).And("is_mentioned=?", true)
+ sess := x.Where("repo_id=?", rid).And("uid=?", uid).And("is_mentioned=?", true)
*tmpSess = *sess
stats.OpenCount, _ = tmpSess.And("is_closed=?", false).Count(new(IssueUser))
*tmpSess = *sess
stats.ClosedCount, _ = tmpSess.And("is_closed=?", true).Count(new(IssueUser))
}
nofilter:
- stats.AssignCount, _ = orm.Where("repo_id=?", rid).And("is_closed=?", isShowClosed).And("assignee_id=?", uid).Count(issue)
- stats.CreateCount, _ = orm.Where("repo_id=?", rid).And("is_closed=?", isShowClosed).And("poster_id=?", uid).Count(issue)
- stats.MentionCount, _ = orm.Where("repo_id=?", rid).And("uid=?", uid).And("is_closed=?", isShowClosed).And("is_mentioned=?", true).Count(new(IssueUser))
+ stats.AssignCount, _ = x.Where("repo_id=?", rid).And("is_closed=?", isShowClosed).And("assignee_id=?", uid).Count(issue)
+ stats.CreateCount, _ = x.Where("repo_id=?", rid).And("is_closed=?", isShowClosed).And("poster_id=?", uid).Count(issue)
+ stats.MentionCount, _ = x.Where("repo_id=?", rid).And("uid=?", uid).And("is_closed=?", isShowClosed).And("is_mentioned=?", true).Count(new(IssueUser))
return stats
}
@@ -378,28 +378,28 @@ nofilter:
func GetUserIssueStats(uid int64, filterMode int) *IssueStats {
stats := &IssueStats{}
issue := new(Issue)
- stats.AssignCount, _ = orm.Where("assignee_id=?", uid).And("is_closed=?", false).Count(issue)
- stats.CreateCount, _ = orm.Where("poster_id=?", uid).And("is_closed=?", false).Count(issue)
+ stats.AssignCount, _ = x.Where("assignee_id=?", uid).And("is_closed=?", false).Count(issue)
+ stats.CreateCount, _ = x.Where("poster_id=?", uid).And("is_closed=?", false).Count(issue)
return stats
}
// UpdateIssue updates information of issue.
func UpdateIssue(issue *Issue) error {
- _, err := orm.Id(issue.Id).AllCols().Update(issue)
+ _, err := x.Id(issue.Id).AllCols().Update(issue)
return err
}
// UpdateIssueUserByStatus updates issue-user pairs by issue status.
func UpdateIssueUserPairsByStatus(iid int64, isClosed bool) error {
rawSql := "UPDATE `issue_user` SET is_closed = ? WHERE issue_id = ?"
- _, err := orm.Exec(rawSql, isClosed, iid)
+ _, err := x.Exec(rawSql, isClosed, iid)
return err
}
// UpdateIssueUserPairByAssignee updates issue-user pair for assigning.
func UpdateIssueUserPairByAssignee(aid, iid int64) error {
rawSql := "UPDATE `issue_user` SET is_assigned = ? WHERE issue_id = ?"
- if _, err := orm.Exec(rawSql, false, iid); err != nil {
+ if _, err := x.Exec(rawSql, false, iid); err != nil {
return err
}
@@ -408,14 +408,14 @@ func UpdateIssueUserPairByAssignee(aid, iid int64) error {
return nil
}
rawSql = "UPDATE `issue_user` SET is_assigned = true WHERE uid = ? AND issue_id = ?"
- _, err := orm.Exec(rawSql, aid, iid)
+ _, err := x.Exec(rawSql, aid, iid)
return err
}
// UpdateIssueUserPairByRead updates issue-user pair for reading.
func UpdateIssueUserPairByRead(uid, iid int64) error {
rawSql := "UPDATE `issue_user` SET is_read = ? WHERE uid = ? AND issue_id = ?"
- _, err := orm.Exec(rawSql, true, uid, iid)
+ _, err := x.Exec(rawSql, true, uid, iid)
return err
}
@@ -423,16 +423,16 @@ func UpdateIssueUserPairByRead(uid, iid int64) error {
func UpdateIssueUserPairsByMentions(uids []int64, iid int64) error {
for _, uid := range uids {
iu := &IssueUser{Uid: uid, IssueId: iid}
- has, err := orm.Get(iu)
+ has, err := x.Get(iu)
if err != nil {
return err
}
iu.IsMentioned = true
if has {
- _, err = orm.Id(iu.Id).AllCols().Update(iu)
+ _, err = x.Id(iu.Id).AllCols().Update(iu)
} else {
- _, err = orm.Insert(iu)
+ _, err = x.Insert(iu)
}
if err != nil {
return err
@@ -467,7 +467,7 @@ func (m *Label) CalOpenIssues() {
// NewLabel creates new label of repository.
func NewLabel(l *Label) error {
- _, err := orm.Insert(l)
+ _, err := x.Insert(l)
return err
}
@@ -478,7 +478,7 @@ func GetLabelById(id int64) (*Label, error) {
}
l := &Label{Id: id}
- has, err := orm.Get(l)
+ has, err := x.Get(l)
if err != nil {
return nil, err
} else if !has {
@@ -490,13 +490,13 @@ func GetLabelById(id int64) (*Label, error) {
// GetLabels returns a list of labels of given repository ID.
func GetLabels(repoId int64) ([]*Label, error) {
labels := make([]*Label, 0, 10)
- err := orm.Where("repo_id=?", repoId).Find(&labels)
+ err := x.Where("repo_id=?", repoId).Find(&labels)
return labels, err
}
// UpdateLabel updates label information.
func UpdateLabel(l *Label) error {
- _, err := orm.Id(l.Id).Update(l)
+ _, err := x.Id(l.Id).Update(l)
return err
}
@@ -516,7 +516,7 @@ func DeleteLabel(repoId int64, strId string) error {
return err
}
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
@@ -569,7 +569,7 @@ func (m *Milestone) CalOpenIssues() {
// NewMilestone creates new milestone of repository.
func NewMilestone(m *Milestone) (err error) {
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
@@ -591,7 +591,7 @@ func NewMilestone(m *Milestone) (err error) {
// GetMilestoneById returns the milestone by given ID.
func GetMilestoneById(id int64) (*Milestone, error) {
m := &Milestone{Id: id}
- has, err := orm.Get(m)
+ has, err := x.Get(m)
if err != nil {
return nil, err
} else if !has {
@@ -603,7 +603,7 @@ func GetMilestoneById(id int64) (*Milestone, error) {
// GetMilestoneByIndex returns the milestone of given repository and index.
func GetMilestoneByIndex(repoId, idx int64) (*Milestone, error) {
m := &Milestone{RepoId: repoId, Index: idx}
- has, err := orm.Get(m)
+ has, err := x.Get(m)
if err != nil {
return nil, err
} else if !has {
@@ -615,13 +615,13 @@ func GetMilestoneByIndex(repoId, idx int64) (*Milestone, error) {
// GetMilestones returns a list of milestones of given repository and status.
func GetMilestones(repoId int64, isClosed bool) ([]*Milestone, error) {
miles := make([]*Milestone, 0, 10)
- err := orm.Where("repo_id=?", repoId).And("is_closed=?", isClosed).Find(&miles)
+ err := x.Where("repo_id=?", repoId).And("is_closed=?", isClosed).Find(&miles)
return miles, err
}
// UpdateMilestone updates information of given milestone.
func UpdateMilestone(m *Milestone) error {
- _, err := orm.Id(m.Id).Update(m)
+ _, err := x.Id(m.Id).Update(m)
return err
}
@@ -632,7 +632,7 @@ func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) {
return err
}
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
@@ -658,7 +658,7 @@ func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) {
// ChangeMilestoneAssign changes assignment of milestone for issue.
func ChangeMilestoneAssign(oldMid, mid int64, issue *Issue) (err error) {
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
@@ -717,7 +717,7 @@ func ChangeMilestoneAssign(oldMid, mid int64, issue *Issue) (err error) {
// DeleteMilestone deletes a milestone.
func DeleteMilestone(m *Milestone) (err error) {
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
@@ -771,13 +771,13 @@ type Comment struct {
IssueId int64
CommitId int64
Line int64
- Content string
+ Content string `xorm:"TEXT"`
Created time.Time `xorm:"CREATED"`
}
// CreateComment creates comment of issue or commit.
func CreateComment(userId, repoId, issueId, commitId, line int64, cmtType int, content string) error {
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
@@ -816,6 +816,6 @@ func CreateComment(userId, repoId, issueId, commitId, line int64, cmtType int, c
// GetIssueComments returns list of comment by given issue id.
func GetIssueComments(issueId int64) ([]Comment, error) {
comments := make([]Comment, 0, 10)
- err := orm.Asc("created").Find(&comments, &Comment{IssueId: issueId})
+ err := x.Asc("created").Find(&comments, &Comment{IssueId: issueId})
return comments, err
}
diff --git a/models/login.go b/models/login.go
index 3efef2f7..e99b61e7 100644
--- a/models/login.go
+++ b/models/login.go
@@ -1,4 +1,4 @@
-// Copyright github.com/juju2013. All rights reserved.
+// 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.
@@ -20,12 +20,13 @@ import (
"github.com/gogits/gogs/modules/log"
)
-// Login types.
+type LoginType int
+
const (
- LT_NOTYPE = iota
- LT_PLAIN
- LT_LDAP
- LT_SMTP
+ NOTYPE LoginType = iota
+ PLAIN
+ LDAP
+ SMTP
)
var (
@@ -34,9 +35,9 @@ var (
ErrAuthenticationUserUsed = errors.New("Authentication has been used by some users")
)
-var LoginTypes = map[int]string{
- LT_LDAP: "LDAP",
- LT_SMTP: "SMTP",
+var LoginTypes = map[LoginType]string{
+ LDAP: "LDAP",
+ SMTP: "SMTP",
}
// Ensure structs implmented interface.
@@ -49,7 +50,6 @@ type LDAPConfig struct {
ldap.Ldapsource
}
-// implement
func (cfg *LDAPConfig) FromDB(bs []byte) error {
return json.Unmarshal(bs, &cfg.Ldapsource)
}
@@ -65,7 +65,6 @@ type SMTPConfig struct {
TLS bool
}
-// implement
func (cfg *SMTPConfig) FromDB(bs []byte) error {
return json.Unmarshal(bs, cfg)
}
@@ -76,13 +75,13 @@ func (cfg *SMTPConfig) ToDB() ([]byte, error) {
type LoginSource struct {
Id int64
- Type int
- Name string `xorm:"unique"`
- IsActived bool `xorm:"not null default false"`
+ Type LoginType
+ Name string `xorm:"UNIQUE"`
+ IsActived bool `xorm:"NOT NULL DEFAULT false"`
Cfg core.Conversion `xorm:"TEXT"`
- Created time.Time `xorm:"created"`
- Updated time.Time `xorm:"updated"`
- AllowAutoRegister bool `xorm:"not null default false"`
+ AllowAutoRegister bool `xorm:"NOT NULL DEFAULT false"`
+ Created time.Time `xorm:"CREATED"`
+ Updated time.Time `xorm:"UPDATED"`
}
func (source *LoginSource) TypeString() string {
@@ -97,61 +96,59 @@ func (source *LoginSource) SMTP() *SMTPConfig {
return source.Cfg.(*SMTPConfig)
}
-// for xorm callback
func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) {
if colName == "type" {
ty := (*val).(int64)
- switch ty {
- case LT_LDAP:
+ switch LoginType(ty) {
+ case LDAP:
source.Cfg = new(LDAPConfig)
- case LT_SMTP:
+ case SMTP:
source.Cfg = new(SMTPConfig)
}
}
}
+func CreateSource(source *LoginSource) error {
+ _, err := x.Insert(source)
+ return err
+}
+
func GetAuths() ([]*LoginSource, error) {
- var auths = make([]*LoginSource, 0)
- err := orm.Find(&auths)
+ var auths = make([]*LoginSource, 0, 5)
+ err := x.Find(&auths)
return auths, err
}
func GetLoginSourceById(id int64) (*LoginSource, error) {
source := new(LoginSource)
- has, err := orm.Id(id).Get(source)
+ has, err := x.Id(id).Get(source)
if err != nil {
return nil, err
- }
- if !has {
+ } else if !has {
return nil, ErrAuthenticationNotExist
}
return source, nil
}
-func AddSource(source *LoginSource) error {
- _, err := orm.Insert(source)
- return err
-}
-
func UpdateSource(source *LoginSource) error {
- _, err := orm.Id(source.Id).AllCols().Update(source)
+ _, err := x.Id(source.Id).AllCols().Update(source)
return err
}
func DelLoginSource(source *LoginSource) error {
- cnt, err := orm.Count(&User{LoginSource: source.Id})
+ cnt, err := x.Count(&User{LoginSource: source.Id})
if err != nil {
return err
}
if cnt > 0 {
return ErrAuthenticationUserUsed
}
- _, err = orm.Id(source.Id).Delete(&LoginSource{})
+ _, err = x.Id(source.Id).Delete(&LoginSource{})
return err
}
-// login a user
-func LoginUser(uname, passwd string) (*User, error) {
+// UserSignIn validates user name and password.
+func UserSignIn(uname, passwd string) (*User, error) {
var u *User
if strings.Contains(uname, "@") {
u = &User{Email: uname}
@@ -159,19 +156,19 @@ func LoginUser(uname, passwd string) (*User, error) {
u = &User{LowerName: strings.ToLower(uname)}
}
- has, err := orm.Get(u)
+ has, err := x.Get(u)
if err != nil {
return nil, err
}
- if u.LoginType == LT_NOTYPE {
+ if u.LoginType == NOTYPE {
if has {
- u.LoginType = LT_PLAIN
+ u.LoginType = PLAIN
}
}
// for plain login, user must have existed.
- if u.LoginType == LT_PLAIN {
+ if u.LoginType == PLAIN {
if !has {
return nil, ErrUserNotExist
}
@@ -185,28 +182,26 @@ func LoginUser(uname, passwd string) (*User, error) {
} else {
if !has {
var sources []LoginSource
- if err = orm.UseBool().Find(&sources,
+ if err = x.UseBool().Find(&sources,
&LoginSource{IsActived: true, AllowAutoRegister: true}); err != nil {
return nil, err
}
for _, source := range sources {
- if source.Type == LT_LDAP {
+ if source.Type == LDAP {
u, err := LoginUserLdapSource(nil, uname, passwd,
source.Id, source.Cfg.(*LDAPConfig), true)
if err == nil {
return u, nil
- } else {
- log.Warn("Fail to login(%s) by LDAP(%s): %v", uname, source.Name, err)
}
- } else if source.Type == LT_SMTP {
+ log.Warn("Fail to login(%s) by LDAP(%s): %v", uname, source.Name, err)
+ } else if source.Type == SMTP {
u, err := LoginUserSMTPSource(nil, uname, passwd,
source.Id, source.Cfg.(*SMTPConfig), true)
if err == nil {
return u, nil
- } else {
- log.Warn("Fail to login(%s) by SMTP(%s): %v", uname, source.Name, err)
}
+ log.Warn("Fail to login(%s) by SMTP(%s): %v", uname, source.Name, err)
}
}
@@ -214,7 +209,7 @@ func LoginUser(uname, passwd string) (*User, error) {
}
var source LoginSource
- hasSource, err := orm.Id(u.LoginSource).Get(&source)
+ hasSource, err := x.Id(u.LoginSource).Get(&source)
if err != nil {
return nil, err
} else if !hasSource {
@@ -224,10 +219,10 @@ func LoginUser(uname, passwd string) (*User, error) {
}
switch u.LoginType {
- case LT_LDAP:
+ case LDAP:
return LoginUserLdapSource(u, u.LoginName, passwd,
source.Id, source.Cfg.(*LDAPConfig), false)
- case LT_SMTP:
+ case SMTP:
return LoginUserSMTPSource(u, u.LoginName, passwd,
source.Id, source.Cfg.(*SMTPConfig), false)
}
@@ -252,7 +247,7 @@ func LoginUserLdapSource(user *User, name, passwd string, sourceId int64, cfg *L
user = &User{
LowerName: strings.ToLower(name),
Name: strings.ToLower(name),
- LoginType: LT_LDAP,
+ LoginType: LDAP,
LoginSource: sourceId,
LoginName: name,
IsActive: true,
@@ -260,7 +255,7 @@ func LoginUserLdapSource(user *User, name, passwd string, sourceId int64, cfg *L
Email: mail,
}
- return RegisterUser(user)
+ return CreateUser(user)
}
type loginAuth struct {
@@ -320,9 +315,8 @@ func SmtpAuth(host string, port int, a smtp.Auth, useTls bool) error {
return err
}
return nil
- } else {
- return ErrUnsupportedLoginType
}
+ return ErrUnsupportedLoginType
}
// Query if name/passwd can login against the LDAP direcotry pool
@@ -358,13 +352,12 @@ func LoginUserSMTPSource(user *User, name, passwd string, sourceId int64, cfg *S
user = &User{
LowerName: strings.ToLower(loginName),
Name: strings.ToLower(loginName),
- LoginType: LT_SMTP,
+ LoginType: SMTP,
LoginSource: sourceId,
LoginName: name,
IsActive: true,
Passwd: passwd,
Email: name,
}
-
- return RegisterUser(user)
+ return CreateUser(user)
}
diff --git a/models/models.go b/models/models.go
index fa65ef30..4e65c00b 100644
--- a/models/models.go
+++ b/models/models.go
@@ -18,7 +18,7 @@ import (
)
var (
- orm *xorm.Engine
+ x *xorm.Engine
tables []interface{}
HasEngine bool
@@ -35,7 +35,7 @@ func init() {
tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch),
new(Action), new(Access), new(Issue), new(Comment), new(Oauth2), new(Follow),
new(Mirror), new(Release), new(LoginSource), new(Webhook), new(IssueUser),
- new(Milestone), new(Label))
+ new(Milestone), new(Label), new(HookTask), new(Team), new(OrgUser), new(TeamUser))
}
func LoadModelsConfig() {
@@ -46,7 +46,9 @@ func LoadModelsConfig() {
DbCfg.Host = setting.Cfg.MustValue("database", "HOST")
DbCfg.Name = setting.Cfg.MustValue("database", "NAME")
DbCfg.User = setting.Cfg.MustValue("database", "USER")
- DbCfg.Pwd = setting.Cfg.MustValue("database", "PASSWD")
+ if len(DbCfg.Pwd) == 0 {
+ DbCfg.Pwd = setting.Cfg.MustValue("database", "PASSWD")
+ }
DbCfg.SslMode = setting.Cfg.MustValue("database", "SSL_MODE")
DbCfg.Path = setting.Cfg.MustValue("database", "PATH", "data/gogs.db")
}
@@ -67,7 +69,6 @@ func NewTestEngine(x *xorm.Engine) (err error) {
}
cnnstr := fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s",
DbCfg.User, DbCfg.Pwd, host, port, DbCfg.Name, DbCfg.SslMode)
- //fmt.Println(cnnstr)
x, err = xorm.NewEngine("postgres", cnnstr)
case "sqlite3":
if !EnableSQLite3 {
@@ -87,7 +88,7 @@ func NewTestEngine(x *xorm.Engine) (err error) {
func SetEngine() (err error) {
switch DbCfg.Type {
case "mysql":
- orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8",
+ x, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8",
DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name))
case "postgres":
var host, port = "127.0.0.1", "5432"
@@ -98,11 +99,11 @@ func SetEngine() (err error) {
if len(fields) > 1 && len(strings.TrimSpace(fields[1])) > 0 {
port = fields[1]
}
- orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s",
+ x, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s",
DbCfg.User, DbCfg.Pwd, host, port, DbCfg.Name, DbCfg.SslMode))
case "sqlite3":
os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm)
- orm, err = xorm.NewEngine("sqlite3", DbCfg.Path)
+ x, err = xorm.NewEngine("sqlite3", DbCfg.Path)
default:
return fmt.Errorf("Unknown database type: %s", DbCfg.Type)
}
@@ -119,11 +120,11 @@ func SetEngine() (err error) {
if err != nil {
return fmt.Errorf("models.init(fail to create xorm.log): %v", err)
}
- orm.Logger = xorm.NewSimpleLogger(f)
+ x.Logger = xorm.NewSimpleLogger(f)
- orm.ShowSQL = true
- orm.ShowDebug = true
- orm.ShowErr = true
+ x.ShowSQL = true
+ x.ShowDebug = true
+ x.ShowErr = true
return nil
}
@@ -131,7 +132,7 @@ func NewEngine() (err error) {
if err = SetEngine(); err != nil {
return err
}
- if err = orm.Sync(tables...); err != nil {
+ if err = x.Sync2(tables...); err != nil {
return fmt.Errorf("sync database struct error: %v\n", err)
}
return nil
@@ -146,24 +147,24 @@ type Statistic struct {
}
func GetStatistic() (stats Statistic) {
- stats.Counter.User, _ = orm.Count(new(User))
- stats.Counter.PublicKey, _ = orm.Count(new(PublicKey))
- stats.Counter.Repo, _ = orm.Count(new(Repository))
- stats.Counter.Watch, _ = orm.Count(new(Watch))
- stats.Counter.Action, _ = orm.Count(new(Action))
- stats.Counter.Access, _ = orm.Count(new(Access))
- stats.Counter.Issue, _ = orm.Count(new(Issue))
- stats.Counter.Comment, _ = orm.Count(new(Comment))
- stats.Counter.Mirror, _ = orm.Count(new(Mirror))
- stats.Counter.Oauth, _ = orm.Count(new(Oauth2))
- stats.Counter.Release, _ = orm.Count(new(Release))
- stats.Counter.LoginSource, _ = orm.Count(new(LoginSource))
- stats.Counter.Webhook, _ = orm.Count(new(Webhook))
- stats.Counter.Milestone, _ = orm.Count(new(Milestone))
+ stats.Counter.User, _ = x.Count(new(User))
+ stats.Counter.PublicKey, _ = x.Count(new(PublicKey))
+ stats.Counter.Repo, _ = x.Count(new(Repository))
+ stats.Counter.Watch, _ = x.Count(new(Watch))
+ stats.Counter.Action, _ = x.Count(new(Action))
+ stats.Counter.Access, _ = x.Count(new(Access))
+ stats.Counter.Issue, _ = x.Count(new(Issue))
+ stats.Counter.Comment, _ = x.Count(new(Comment))
+ stats.Counter.Mirror, _ = x.Count(new(Mirror))
+ stats.Counter.Oauth, _ = x.Count(new(Oauth2))
+ stats.Counter.Release, _ = x.Count(new(Release))
+ stats.Counter.LoginSource, _ = x.Count(new(LoginSource))
+ stats.Counter.Webhook, _ = x.Count(new(Webhook))
+ stats.Counter.Milestone, _ = x.Count(new(Milestone))
return
}
// DumpDatabase dumps all data from database to file system.
func DumpDatabase(filePath string) error {
- return orm.DumpAllToFile(filePath)
+ return x.DumpAllToFile(filePath)
}
diff --git a/models/oauth2.go b/models/oauth2.go
index 61044d68..4b024a26 100644
--- a/models/oauth2.go
+++ b/models/oauth2.go
@@ -8,16 +8,16 @@ import (
"errors"
)
-// OT: Oauth2 Type
+type OauthType int
+
const (
- OT_GITHUB = iota + 1
- OT_GOOGLE
- OT_TWITTER
- OT_QQ
- OT_WEIBO
- OT_BITBUCKET
- OT_OSCHINA
- OT_FACEBOOK
+ GITHUB OauthType = iota + 1
+ GOOGLE
+ TWITTER
+ QQ
+ WEIBO
+ BITBUCKET
+ FACEBOOK
)
var (
@@ -35,18 +35,18 @@ type Oauth2 struct {
}
func BindUserOauth2(userId, oauthId int64) error {
- _, err := orm.Id(oauthId).Update(&Oauth2{Uid: userId})
+ _, err := x.Id(oauthId).Update(&Oauth2{Uid: userId})
return err
}
func AddOauth2(oa *Oauth2) error {
- _, err := orm.Insert(oa)
+ _, err := x.Insert(oa)
return err
}
func GetOauth2(identity string) (oa *Oauth2, err error) {
oa = &Oauth2{Identity: identity}
- isExist, err := orm.Get(oa)
+ isExist, err := x.Get(oa)
if err != nil {
return
} else if !isExist {
@@ -60,7 +60,7 @@ func GetOauth2(identity string) (oa *Oauth2, err error) {
func GetOauth2ById(id int64) (oa *Oauth2, err error) {
oa = new(Oauth2)
- has, err := orm.Id(id).Get(oa)
+ has, err := x.Id(id).Get(oa)
if err != nil {
return nil, err
} else if !has {
@@ -71,18 +71,18 @@ func GetOauth2ById(id int64) (oa *Oauth2, err error) {
// GetOauthByUserId returns list of oauthes that are releated to given user.
func GetOauthByUserId(uid int64) (oas []*Oauth2, err error) {
- err = orm.Find(&oas, Oauth2{Uid: uid})
+ err = x.Find(&oas, Oauth2{Uid: uid})
return oas, err
}
// DeleteOauth2ById deletes a oauth2 by ID.
func DeleteOauth2ById(id int64) error {
- _, err := orm.Delete(&Oauth2{Id: id})
+ _, err := x.Delete(&Oauth2{Id: id})
return err
}
// CleanUnbindOauth deletes all unbind OAuthes.
func CleanUnbindOauth() error {
- _, err := orm.Delete(&Oauth2{Uid: -1})
+ _, err := x.Delete(&Oauth2{Uid: -1})
return err
}
diff --git a/models/org.go b/models/org.go
new file mode 100644
index 00000000..025759b0
--- /dev/null
+++ b/models/org.go
@@ -0,0 +1,236 @@
+// 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 models
+
+import (
+ "strings"
+
+ "github.com/gogits/gogs/modules/base"
+)
+
+// GetOwnerTeam returns owner team of organization.
+func (org *User) GetOwnerTeam() (*Team, error) {
+ t := &Team{
+ OrgId: org.Id,
+ Name: OWNER_TEAM,
+ }
+ _, err := x.Get(t)
+ return t, err
+}
+
+// CreateOrganization creates record of a new organization.
+func CreateOrganization(org, owner *User) (*User, error) {
+ if !IsLegalName(org.Name) {
+ return nil, ErrUserNameIllegal
+ }
+
+ isExist, err := IsUserExist(org.Name)
+ if err != nil {
+ return nil, err
+ } else if isExist {
+ return nil, ErrUserAlreadyExist
+ }
+
+ isExist, err = IsEmailUsed(org.Email)
+ if err != nil {
+ return nil, err
+ } else if isExist {
+ return nil, ErrEmailAlreadyUsed
+ }
+
+ org.LowerName = strings.ToLower(org.Name)
+ org.FullName = org.Name
+ org.Avatar = base.EncodeMd5(org.Email)
+ org.AvatarEmail = org.Email
+ // No password for organization.
+ org.NumTeams = 1
+ org.NumMembers = 1
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err = sess.Begin(); err != nil {
+ return nil, err
+ }
+
+ if _, err = sess.Insert(org); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ // Create default owner team.
+ t := &Team{
+ OrgId: org.Id,
+ Name: OWNER_TEAM,
+ Authorize: ORG_ADMIN,
+ NumMembers: 1,
+ }
+ if _, err = sess.Insert(t); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ // Add initial creator to organization and owner team.
+ ou := &OrgUser{
+ Uid: owner.Id,
+ OrgId: org.Id,
+ IsOwner: true,
+ NumTeam: 1,
+ }
+ if _, err = sess.Insert(ou); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ tu := &TeamUser{
+ Uid: owner.Id,
+ OrgId: org.Id,
+ TeamId: t.Id,
+ }
+ if _, err = sess.Insert(tu); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ return org, sess.Commit()
+}
+
+// TODO: need some kind of mechanism to record failure.
+// DeleteOrganization completely and permanently deletes everything of organization.
+func DeleteOrganization(org *User) (err error) {
+ if err := DeleteUser(org); err != nil {
+ return err
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err = sess.Begin(); err != nil {
+ return err
+ }
+
+ if _, err = sess.Delete(&Team{OrgId: org.Id}); err != nil {
+ sess.Rollback()
+ return err
+ }
+ if _, err = sess.Delete(&OrgUser{OrgId: org.Id}); err != nil {
+ sess.Rollback()
+ return err
+ }
+ if _, err = sess.Delete(&TeamUser{OrgId: org.Id}); err != nil {
+ sess.Rollback()
+ return err
+ }
+ return sess.Commit()
+}
+
+type AuthorizeType int
+
+const (
+ ORG_READABLE AuthorizeType = iota + 1
+ ORG_WRITABLE
+ ORG_ADMIN
+)
+
+const OWNER_TEAM = "Owner"
+
+// Team represents a organization team.
+type Team struct {
+ Id int64
+ OrgId int64 `xorm:"INDEX"`
+ Name string
+ Description string
+ Authorize AuthorizeType
+ RepoIds string `xorm:"TEXT"`
+ NumMembers int
+ NumRepos int
+}
+
+// NewTeam creates a record of new team.
+func NewTeam(t *Team) error {
+ _, err := x.Insert(t)
+ return err
+}
+
+func UpdateTeam(t *Team) error {
+ if len(t.Description) > 255 {
+ t.Description = t.Description[:255]
+ }
+
+ _, err := x.Id(t.Id).AllCols().Update(t)
+ return err
+}
+
+// ________ ____ ___
+// \_____ \_______ ____ | | \______ ___________
+// / | \_ __ \/ ___\| | / ___// __ \_ __ \
+// / | \ | \/ /_/ > | /\___ \\ ___/| | \/
+// \_______ /__| \___ /|______//____ >\___ >__|
+// \/ /_____/ \/ \/
+
+// OrgUser represents an organization-user relation.
+type OrgUser struct {
+ Id int64
+ Uid int64 `xorm:"INDEX"`
+ OrgId int64 `xorm:"INDEX"`
+ IsPublic bool
+ IsOwner bool
+ NumTeam int
+}
+
+// GetOrgUsersByUserId returns all organization-user relations by user ID.
+func GetOrgUsersByUserId(uid int64) ([]*OrgUser, error) {
+ ous := make([]*OrgUser, 0, 10)
+ err := x.Where("uid=?", uid).Find(&ous)
+ return ous, err
+}
+
+// GetOrgUsersByOrgId returns all organization-user relations by organization ID.
+func GetOrgUsersByOrgId(orgId int64) ([]*OrgUser, error) {
+ ous := make([]*OrgUser, 0, 10)
+ err := x.Where("org_id=?", orgId).Find(&ous)
+ return ous, err
+}
+
+func GetOrganizationCount(u *User) (int64, error) {
+ return x.Where("uid=?", u.Id).Count(new(OrgUser))
+}
+
+// IsOrganizationOwner returns true if given user ID is in the owner team.
+func IsOrganizationOwner(orgId, uid int64) bool {
+ has, _ := x.Where("is_owner=?", true).Get(&OrgUser{Uid: uid, OrgId: orgId})
+ return has
+}
+
+// ___________ ____ ___
+// \__ ___/___ _____ _____ | | \______ ___________
+// | |_/ __ \\__ \ / \| | / ___// __ \_ __ \
+// | |\ ___/ / __ \| Y Y \ | /\___ \\ ___/| | \/
+// |____| \___ >____ /__|_| /______//____ >\___ >__|
+// \/ \/ \/ \/ \/
+
+// TeamUser represents an team-user relation.
+type TeamUser struct {
+ Id int64
+ Uid int64
+ OrgId int64 `xorm:"INDEX"`
+ TeamId int64
+}
+
+// GetTeamMembers returns all members in given team of organization.
+func GetTeamMembers(orgId, teamId int64) ([]*User, error) {
+ tus := make([]*TeamUser, 0, 10)
+ err := x.Where("org_id=?", orgId).And("team_id=?", teamId).Find(&tus)
+ if err != nil {
+ return nil, err
+ }
+
+ us := make([]*User, len(tus))
+ for i, tu := range tus {
+ us[i], err = GetUserById(tu.Uid)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return us, nil
+}
diff --git a/models/publickey.go b/models/publickey.go
index 556db964..603ff364 100644
--- a/models/publickey.go
+++ b/models/publickey.go
@@ -19,9 +19,9 @@ import (
"time"
"github.com/Unknwon/com"
- qlog "github.com/qiniu/log"
"github.com/gogits/gogs/modules/log"
+ "github.com/gogits/gogs/modules/process"
)
const (
@@ -37,7 +37,7 @@ var (
var sshOpLocker = sync.Mutex{}
var (
- sshPath string // SSH directory.
+ SshPath string // SSH directory.
appPath string // Execution(binary) path.
)
@@ -54,7 +54,7 @@ func exePath() (string, error) {
func homeDir() string {
home, err := com.HomeDir()
if err != nil {
- qlog.Fatalln(err)
+ log.Fatal("Fail to get home directory: %v", err)
}
return home
}
@@ -63,13 +63,13 @@ func init() {
var err error
if appPath, err = exePath(); err != nil {
- qlog.Fatalf("publickey.init(fail to get app path): %v\n", err)
+ log.Fatal("publickey.init(fail to get app path): %v\n", err)
}
// Determine and create .ssh path.
- sshPath = filepath.Join(homeDir(), ".ssh")
- if err = os.MkdirAll(sshPath, os.ModePerm); err != nil {
- qlog.Fatalf("publickey.init(fail to create sshPath(%s)): %v\n", sshPath, err)
+ SshPath = filepath.Join(homeDir(), ".ssh")
+ if err = os.MkdirAll(SshPath, os.ModePerm); err != nil {
+ log.Fatal("publickey.init(fail to create SshPath(%s)): %v\n", SshPath, err)
}
}
@@ -94,7 +94,7 @@ func saveAuthorizedKeyFile(key *PublicKey) error {
sshOpLocker.Lock()
defer sshOpLocker.Unlock()
- fpath := filepath.Join(sshPath, "authorized_keys")
+ fpath := filepath.Join(SshPath, "authorized_keys")
f, err := os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
if err != nil {
return err
@@ -107,7 +107,7 @@ func saveAuthorizedKeyFile(key *PublicKey) error {
// AddPublicKey adds new public key to database and authorized_keys file.
func AddPublicKey(key *PublicKey) (err error) {
- has, err := orm.Get(key)
+ has, err := x.Get(key)
if err != nil {
return err
} else if has {
@@ -121,7 +121,7 @@ func AddPublicKey(key *PublicKey) (err error) {
if err = ioutil.WriteFile(tmpPath, []byte(key.Content), os.ModePerm); err != nil {
return err
}
- stdout, stderr, err := com.ExecCmd("ssh-keygen", "-l", "-f", tmpPath)
+ stdout, stderr, err := process.Exec("AddPublicKey", "ssh-keygen", "-l", "-f", tmpPath)
if err != nil {
return errors.New("ssh-keygen -l -f: " + stderr)
} else if len(stdout) < 2 {
@@ -130,11 +130,11 @@ func AddPublicKey(key *PublicKey) (err error) {
key.Fingerprint = strings.Split(stdout, " ")[1]
// Save SSH key.
- if _, err = orm.Insert(key); err != nil {
+ if _, err = x.Insert(key); err != nil {
return err
} else if err = saveAuthorizedKeyFile(key); err != nil {
// Roll back.
- if _, err2 := orm.Delete(key); err2 != nil {
+ if _, err2 := x.Delete(key); err2 != nil {
return err2
}
return err
@@ -146,7 +146,7 @@ func AddPublicKey(key *PublicKey) (err error) {
// ListPublicKey returns a list of all public keys that user has.
func ListPublicKey(uid int64) ([]PublicKey, error) {
keys := make([]PublicKey, 0, 5)
- err := orm.Find(&keys, &PublicKey{OwnerId: uid})
+ err := x.Find(&keys, &PublicKey{OwnerId: uid})
return keys, err
}
@@ -161,7 +161,7 @@ func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error {
}
defer fr.Close()
- fw, err := os.Create(tmpP)
+ fw, err := os.OpenFile(tmpP, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
if err != nil {
return err
}
@@ -205,19 +205,19 @@ func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error {
// DeletePublicKey deletes SSH key information both in database and authorized_keys file.
func DeletePublicKey(key *PublicKey) error {
- has, err := orm.Get(key)
+ has, err := x.Get(key)
if err != nil {
return err
} else if !has {
return ErrKeyNotExist
}
- if _, err = orm.Delete(key); err != nil {
+ if _, err = x.Delete(key); err != nil {
return err
}
- fpath := filepath.Join(sshPath, "authorized_keys")
- tmpPath := filepath.Join(sshPath, "authorized_keys.tmp")
+ fpath := filepath.Join(SshPath, "authorized_keys")
+ tmpPath := filepath.Join(SshPath, "authorized_keys.tmp")
log.Trace("publickey.DeletePublicKey(authorized_keys): %s", fpath)
if err = rewriteAuthorizedKeys(key, fpath, tmpPath); err != nil {
diff --git a/models/release.go b/models/release.go
index e6c3d561..3e1a7811 100644
--- a/models/release.go
+++ b/models/release.go
@@ -6,15 +6,16 @@ package models
import (
"errors"
+ "sort"
"strings"
"time"
- "github.com/Unknwon/com"
"github.com/gogits/git"
)
var (
ErrReleaseAlreadyExist = errors.New("Release already exist")
+ ErrReleaseNotExist = errors.New("Release does not exist")
)
// Release represents a release of repository.
@@ -23,21 +24,17 @@ type Release struct {
RepoId int64
PublisherId int64
Publisher *User `xorm:"-"`
- Title string
TagName string
LowerTagName string
- SHA1 string
+ Target string
+ Title string
+ Sha1 string `xorm:"VARCHAR(40)"`
NumCommits int
NumCommitsBehind int `xorm:"-"`
Note string `xorm:"TEXT"`
+ IsDraft bool `xorm:"NOT NULL DEFAULT false"`
IsPrerelease bool
- Created time.Time `xorm:"created"`
-}
-
-// GetReleasesByRepoId returns a list of releases of repository.
-func GetReleasesByRepoId(repoId int64) (rels []*Release, err error) {
- err = orm.Desc("created").Find(&rels, Release{RepoId: repoId})
- return rels, err
+ Created time.Time `xorm:"CREATED"`
}
// IsReleaseExist returns true if release with given tag name already exists.
@@ -46,7 +43,34 @@ func IsReleaseExist(repoId int64, tagName string) (bool, error) {
return false, nil
}
- return orm.Get(&Release{RepoId: repoId, LowerTagName: strings.ToLower(tagName)})
+ return x.Get(&Release{RepoId: repoId, LowerTagName: strings.ToLower(tagName)})
+}
+
+func createTag(gitRepo *git.Repository, rel *Release) error {
+ // Only actual create when publish.
+ if !rel.IsDraft {
+ if !gitRepo.IsTagExist(rel.TagName) {
+ commit, err := gitRepo.GetCommitOfBranch(rel.Target)
+ if err != nil {
+ return err
+ }
+
+ if err = gitRepo.CreateTag(rel.TagName, commit.Id.String()); err != nil {
+ return err
+ }
+ } else {
+ commit, err := gitRepo.GetCommitOfTag(rel.TagName)
+ if err != nil {
+ return err
+ }
+
+ rel.NumCommits, err = commit.CommitsCount()
+ if err != nil {
+ return err
+ }
+ }
+ }
+ return nil
}
// CreateRelease creates a new release of repository.
@@ -58,26 +82,65 @@ func CreateRelease(gitRepo *git.Repository, rel *Release) error {
return ErrReleaseAlreadyExist
}
- if !gitRepo.IsTagExist(rel.TagName) {
- _, stderr, err := com.ExecCmdDir(gitRepo.Path, "git", "tag", rel.TagName, "-m", rel.Title)
- if err != nil {
- return err
- } else if strings.Contains(stderr, "fatal:") {
- return errors.New(stderr)
- }
- } else {
- commit, err := gitRepo.GetCommitOfTag(rel.TagName)
- if err != nil {
- return err
- }
+ if err = createTag(gitRepo, rel); err != nil {
+ return err
+ }
+ rel.LowerTagName = strings.ToLower(rel.TagName)
+ _, err = x.InsertOne(rel)
+ return err
+}
- rel.NumCommits, err = commit.CommitsCount()
- if err != nil {
- return err
- }
+// GetRelease returns release by given ID.
+func GetRelease(repoId int64, tagName string) (*Release, error) {
+ isExist, err := IsReleaseExist(repoId, tagName)
+ if err != nil {
+ return nil, err
+ } else if !isExist {
+ return nil, ErrReleaseNotExist
}
- rel.LowerTagName = strings.ToLower(rel.TagName)
- _, err = orm.InsertOne(rel)
+ rel := &Release{RepoId: repoId, LowerTagName: strings.ToLower(tagName)}
+ _, err = x.Get(rel)
+ return rel, err
+}
+
+// GetReleasesByRepoId returns a list of releases of repository.
+func GetReleasesByRepoId(repoId int64) (rels []*Release, err error) {
+ err = x.Desc("created").Find(&rels, Release{RepoId: repoId})
+ return rels, err
+}
+
+type ReleaseSorter struct {
+ rels []*Release
+}
+
+func (rs *ReleaseSorter) Len() int {
+ return len(rs.rels)
+}
+
+func (rs *ReleaseSorter) Less(i, j int) bool {
+ diffNum := rs.rels[i].NumCommits - rs.rels[j].NumCommits
+ if diffNum != 0 {
+ return diffNum > 0
+ }
+ return rs.rels[i].Created.After(rs.rels[j].Created)
+}
+
+func (rs *ReleaseSorter) Swap(i, j int) {
+ rs.rels[i], rs.rels[j] = rs.rels[j], rs.rels[i]
+}
+
+// SortReleases sorts releases by number of commits and created time.
+func SortReleases(rels []*Release) {
+ sorter := &ReleaseSorter{rels: rels}
+ sort.Sort(sorter)
+}
+
+// UpdateRelease updates information of a release.
+func UpdateRelease(gitRepo *git.Repository, rel *Release) (err error) {
+ if err = createTag(gitRepo, rel); err != nil {
+ return err
+ }
+ _, err = x.Id(rel.Id).AllCols().Update(rel)
return err
}
diff --git a/models/repo.go b/models/repo.go
index 60082734..8eec131f 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -9,9 +9,9 @@ import (
"fmt"
"io/ioutil"
"os"
- "os/exec"
"path"
"path/filepath"
+ "sort"
"strings"
"time"
"unicode/utf8"
@@ -24,9 +24,14 @@ import (
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/bin"
"github.com/gogits/gogs/modules/log"
+ "github.com/gogits/gogs/modules/process"
"github.com/gogits/gogs/modules/setting"
)
+const (
+ TPL_UPDATE_HOOK = "#!/usr/bin/env %s\n%s update $1 $2 $3\n"
+)
+
var (
ErrRepoAlreadyExist = errors.New("Repository already exist")
ErrRepoNotExist = errors.New("Repository does not exist")
@@ -75,19 +80,21 @@ func LoadRepoConfig() {
LanguageIgns = typeFiles[0]
Licenses = typeFiles[1]
+ sort.Strings(LanguageIgns)
+ sort.Strings(Licenses)
}
func NewRepoContext() {
zip.Verbose = false
// Check if server has basic git setting.
- stdout, stderr, err := com.ExecCmd("git", "config", "--get", "user.name")
+ stdout, stderr, err := process.Exec("NewRepoContext(get setting)", "git", "config", "--get", "user.name")
if strings.Contains(stderr, "fatal:") {
log.Fatal("repo.NewRepoContext(fail to get git user.name): %s", stderr)
} else if err != nil || len(strings.TrimSpace(stdout)) == 0 {
- if _, stderr, err = com.ExecCmd("git", "config", "--global", "user.email", "gogitservice@gmail.com"); err != nil {
+ if _, stderr, err = process.Exec("NewRepoContext(set email)", "git", "config", "--global", "user.email", "gogitservice@gmail.com"); err != nil {
log.Fatal("repo.NewRepoContext(fail to set git user.email): %s", stderr)
- } else if _, stderr, err = com.ExecCmd("git", "config", "--global", "user.name", "Gogs"); err != nil {
+ } else if _, stderr, err = process.Exec("NewRepoContext(set name)", "git", "config", "--global", "user.name", "Gogs"); err != nil {
log.Fatal("repo.NewRepoContext(fail to set git user.name): %s", stderr)
}
}
@@ -106,11 +113,11 @@ func NewRepoContext() {
// Repository represents a git repository.
type Repository struct {
Id int64
- OwnerId int64 `xorm:"unique(s)"`
+ OwnerId int64 `xorm:"UNIQUE(s)"`
Owner *User `xorm:"-"`
ForkId int64
- LowerName string `xorm:"unique(s) index not null"`
- Name string `xorm:"index not null"`
+ LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
+ Name string `xorm:"INDEX NOT NULL"`
Description string
Website string
NumWatches int
@@ -128,8 +135,8 @@ type Repository struct {
IsBare bool
IsGoget bool
DefaultBranch string
- Created time.Time `xorm:"created"`
- Updated time.Time `xorm:"updated"`
+ Created time.Time `xorm:"CREATED"`
+ Updated time.Time `xorm:"UPDATED"`
}
func (repo *Repository) GetOwner() (err error) {
@@ -140,7 +147,7 @@ func (repo *Repository) GetOwner() (err error) {
// IsRepositoryExist returns true if the repository with given name under user has already existed.
func IsRepositoryExist(u *User, repoName string) (bool, error) {
repo := Repository{OwnerId: u.Id}
- has, err := orm.Where("lower_name = ?", strings.ToLower(repoName)).Get(&repo)
+ has, err := x.Where("lower_name = ?", strings.ToLower(repoName)).Get(&repo)
if err != nil {
return has, err
} else if !has {
@@ -151,7 +158,7 @@ func IsRepositoryExist(u *User, repoName string) (bool, error) {
}
var (
- illegalEquals = []string{"raw", "install", "api", "avatar", "user", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
+ illegalEquals = []string{"raw", "install", "api", "avatar", "user", "org", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
illegalSuffixs = []string{".git"}
)
@@ -181,9 +188,30 @@ type Mirror struct {
NextUpdate time.Time
}
+// MirrorRepository creates a mirror repository from source.
+func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error {
+ // TODO: need timeout.
+ _, stderr, err := process.Exec(fmt.Sprintf("MirrorRepository: %s/%s", userName, repoName),
+ "git", "clone", "--mirror", url, repoPath)
+ if err != nil {
+ return errors.New("git clone --mirror: " + stderr)
+ }
+
+ if _, err = x.InsertOne(&Mirror{
+ RepoId: repoId,
+ RepoName: strings.ToLower(userName + "/" + repoName),
+ Interval: 24,
+ NextUpdate: time.Now().Add(24 * time.Hour),
+ }); err != nil {
+ return err
+ }
+
+ return git.UnpackRefs(repoPath)
+}
+
func GetMirror(repoId int64) (*Mirror, error) {
m := &Mirror{RepoId: repoId}
- has, err := orm.Get(m)
+ has, err := x.Get(m)
if err != nil {
return nil, err
} else if !has {
@@ -193,24 +221,26 @@ func GetMirror(repoId int64) (*Mirror, error) {
}
func UpdateMirror(m *Mirror) error {
- _, err := orm.Id(m.Id).Update(m)
+ _, err := x.Id(m.Id).Update(m)
return err
}
// MirrorUpdate checks and updates mirror repositories.
func MirrorUpdate() {
- if err := orm.Iterate(new(Mirror), func(idx int, bean interface{}) error {
+ if err := x.Iterate(new(Mirror), func(idx int, bean interface{}) error {
m := bean.(*Mirror)
if m.NextUpdate.After(time.Now()) {
return nil
}
+ // TODO: need timeout.
repoPath := filepath.Join(setting.RepoRootPath, m.RepoName+".git")
- _, stderr, err := com.ExecCmdDir(repoPath, "git", "remote", "update")
- if err != nil {
+ if _, stderr, err := process.ExecDir(
+ repoPath, fmt.Sprintf("MirrorUpdate: %s", repoPath),
+ "git", "remote", "update"); err != nil {
return errors.New("git remote update: " + stderr)
} else if err = git.UnpackRefs(repoPath); err != nil {
- return err
+ return errors.New("UnpackRefs: " + err.Error())
}
m.NextUpdate = time.Now().Add(time.Duration(m.Interval) * time.Hour)
@@ -220,28 +250,9 @@ func MirrorUpdate() {
}
}
-// MirrorRepository creates a mirror repository from source.
-func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error {
- _, stderr, err := com.ExecCmd("git", "clone", "--mirror", url, repoPath)
- if err != nil {
- return errors.New("git clone --mirror: " + stderr)
- }
-
- if _, err = orm.InsertOne(&Mirror{
- RepoId: repoId,
- RepoName: strings.ToLower(userName + "/" + repoName),
- Interval: 24,
- NextUpdate: time.Now().Add(24 * time.Hour),
- }); err != nil {
- return err
- }
-
- return git.UnpackRefs(repoPath)
-}
-
// MigrateRepository migrates a existing repository from other project hosting.
-func MigrateRepository(user *User, name, desc string, private, mirror bool, url string) (*Repository, error) {
- repo, err := CreateRepository(user, name, desc, "", "", private, mirror, false)
+func MigrateRepository(u *User, name, desc string, private, mirror bool, url string) (*Repository, error) {
+ repo, err := CreateRepository(u, name, desc, "", "", private, mirror, false)
if err != nil {
return nil, err
}
@@ -250,144 +261,45 @@ func MigrateRepository(user *User, name, desc string, private, mirror bool, url
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()))
os.MkdirAll(tmpDir, os.ModePerm)
- repoPath := RepoPath(user.Name, name)
+ repoPath := RepoPath(u.Name, name)
repo.IsBare = false
if mirror {
- if err = MirrorRepository(repo.Id, user.Name, repo.Name, repoPath, url); err != nil {
+ if err = MirrorRepository(repo.Id, u.Name, repo.Name, repoPath, url); err != nil {
return repo, err
}
repo.IsMirror = true
return repo, UpdateRepository(repo)
}
+ // TODO: need timeout.
// Clone from local repository.
- _, stderr, err := com.ExecCmd("git", "clone", repoPath, tmpDir)
+ _, stderr, err := process.Exec(
+ fmt.Sprintf("MigrateRepository(git clone): %s", repoPath),
+ "git", "clone", repoPath, tmpDir)
if err != nil {
return repo, errors.New("git clone: " + stderr)
}
+ // TODO: need timeout.
// Pull data from source.
- _, stderr, err = com.ExecCmdDir(tmpDir, "git", "pull", url)
- if err != nil {
+ if _, stderr, err = process.ExecDir(
+ tmpDir, fmt.Sprintf("MigrateRepository(git pull): %s", repoPath),
+ "git", "pull", url); err != nil {
return repo, errors.New("git pull: " + stderr)
}
+ // TODO: need timeout.
// Push data to local repository.
- if _, stderr, err = com.ExecCmdDir(tmpDir, "git", "push", "origin", "master"); err != nil {
+ if _, stderr, err = process.ExecDir(
+ tmpDir, fmt.Sprintf("MigrateRepository(git push): %s", repoPath),
+ "git", "push", "origin", "master"); err != nil {
return repo, errors.New("git push: " + stderr)
}
return repo, UpdateRepository(repo)
}
-// CreateRepository creates a repository for given user or orgnaziation.
-func CreateRepository(user *User, name, desc, lang, license string, private, mirror, initReadme bool) (*Repository, error) {
- if !IsLegalName(name) {
- return nil, ErrRepoNameIllegal
- }
-
- isExist, err := IsRepositoryExist(user, name)
- if err != nil {
- return nil, err
- } else if isExist {
- return nil, ErrRepoAlreadyExist
- }
-
- repo := &Repository{
- OwnerId: user.Id,
- Name: name,
- LowerName: strings.ToLower(name),
- Description: desc,
- IsPrivate: private,
- IsBare: lang == "" && license == "" && !initReadme,
- }
- if !repo.IsBare {
- repo.DefaultBranch = "master"
- }
-
- repoPath := RepoPath(user.Name, repo.Name)
-
- sess := orm.NewSession()
- defer sess.Close()
- sess.Begin()
-
- if _, err = sess.Insert(repo); err != nil {
- if err2 := os.RemoveAll(repoPath); err2 != nil {
- log.Error("repo.CreateRepository(repo): %v", err)
- return nil, errors.New(fmt.Sprintf(
- "delete repo directory %s/%s failed(1): %v", user.Name, repo.Name, err2))
- }
- sess.Rollback()
- return nil, err
- }
-
- mode := AU_WRITABLE
- if mirror {
- mode = AU_READABLE
- }
- access := Access{
- UserName: user.LowerName,
- RepoName: strings.ToLower(path.Join(user.Name, repo.Name)),
- Mode: mode,
- }
- if _, err = sess.Insert(&access); err != nil {
- sess.Rollback()
- if err2 := os.RemoveAll(repoPath); err2 != nil {
- log.Error("repo.CreateRepository(access): %v", err)
- return nil, errors.New(fmt.Sprintf(
- "delete repo directory %s/%s failed(2): %v", user.Name, repo.Name, err2))
- }
- return nil, err
- }
-
- rawSql := "UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?"
- if _, err = sess.Exec(rawSql, user.Id); err != nil {
- sess.Rollback()
- if err2 := os.RemoveAll(repoPath); err2 != nil {
- log.Error("repo.CreateRepository(repo count): %v", err)
- return nil, errors.New(fmt.Sprintf(
- "delete repo directory %s/%s failed(3): %v", user.Name, repo.Name, err2))
- }
- return nil, err
- }
-
- if err = sess.Commit(); err != nil {
- sess.Rollback()
- if err2 := os.RemoveAll(repoPath); err2 != nil {
- log.Error("repo.CreateRepository(commit): %v", err)
- return nil, errors.New(fmt.Sprintf(
- "delete repo directory %s/%s failed(3): %v", user.Name, repo.Name, err2))
- }
- return nil, err
- }
-
- if err = WatchRepo(user.Id, repo.Id, true); err != nil {
- log.Error("repo.CreateRepository(WatchRepo): %v", err)
- }
-
- if err = NewRepoAction(user, repo); err != nil {
- log.Error("repo.CreateRepository(NewRepoAction): %v", err)
- }
-
- // No need for init for mirror.
- if mirror {
- return repo, nil
- }
-
- if err = initRepository(repoPath, user, repo, initReadme, lang, license); err != nil {
- return nil, err
- }
-
- c := exec.Command("git", "update-server-info")
- c.Dir = repoPath
- if err = c.Run(); err != nil {
- log.Error("repo.CreateRepository(exec update-server-info): %v", err)
- }
-
- return repo, nil
-}
-
// extractGitBareZip extracts git-bare.zip to repository path.
func extractGitBareZip(repoPath string) error {
z, err := zip.Open(filepath.Join(setting.RepoRootPath, "git-bare.zip"))
@@ -402,15 +314,22 @@ func extractGitBareZip(repoPath string) error {
// initRepoCommit temporarily changes with work directory.
func initRepoCommit(tmpPath string, sig *git.Signature) (err error) {
var stderr string
- if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "add", "--all"); err != nil {
+ if _, stderr, err = process.ExecDir(
+ tmpPath, fmt.Sprintf("initRepoCommit(git add): %s", tmpPath),
+ "git", "add", "--all"); err != nil {
return errors.New("git add: " + stderr)
}
- if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
+
+ if _, stderr, err = process.ExecDir(
+ tmpPath, fmt.Sprintf("initRepoCommit(git commit): %s", tmpPath),
+ "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
"-m", "Init commit"); err != nil {
return errors.New("git commit: " + stderr)
}
- if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "push", "origin", "master"); err != nil {
+ if _, stderr, err = process.ExecDir(
+ tmpPath, fmt.Sprintf("initRepoCommit(git push): %s", tmpPath),
+ "git", "push", "origin", "master"); err != nil {
return errors.New("git push: " + stderr)
}
return nil
@@ -447,7 +366,7 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep
rp := strings.NewReplacer("\\", "/", " ", "\\ ")
// hook/post-update
if err := createHookUpdate(filepath.Join(repoPath, "hooks", "update"),
- fmt.Sprintf("#!/usr/bin/env %s\n%s update $1 $2 $3\n", setting.ScriptType,
+ fmt.Sprintf(TPL_UPDATE_HOOK, setting.ScriptType,
rp.Replace(appPath))); err != nil {
return err
}
@@ -468,9 +387,11 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep
tmpDir := filepath.Join(os.TempDir(), base.ToStr(time.Now().Nanosecond()))
os.MkdirAll(tmpDir, os.ModePerm)
- _, stderr, err := com.ExecCmd("git", "clone", repoPath, tmpDir)
+ _, stderr, err := process.Exec(
+ fmt.Sprintf("initRepository(git clone): %s", repoPath),
+ "git", "clone", repoPath, tmpDir)
if err != nil {
- return errors.New("git clone: " + stderr)
+ return errors.New("initRepository(git clone): " + stderr)
}
// README
@@ -486,22 +407,40 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep
// .gitignore
if repoLang != "" {
filePath := "conf/gitignore/" + repoLang
- if com.IsFile(filePath) {
- if err := com.Copy(filePath,
- filepath.Join(tmpDir, fileName["gitign"])); err != nil {
+ targetPath := path.Join(tmpDir, fileName["gitign"])
+ data, err := bin.Asset(filePath)
+ if err == nil {
+ if err = ioutil.WriteFile(targetPath, data, os.ModePerm); err != nil {
return err
}
+ } else {
+ // Check custom files.
+ filePath = path.Join(setting.CustomPath, "conf/gitignore", repoLang)
+ if com.IsFile(filePath) {
+ if err := com.Copy(filePath, targetPath); err != nil {
+ return err
+ }
+ }
}
}
// LICENSE
if license != "" {
filePath := "conf/license/" + license
- if com.IsFile(filePath) {
- if err := com.Copy(filePath,
- filepath.Join(tmpDir, fileName["license"])); err != nil {
+ targetPath := path.Join(tmpDir, fileName["license"])
+ data, err := bin.Asset(filePath)
+ if err == nil {
+ if err = ioutil.WriteFile(targetPath, data, os.ModePerm); err != nil {
return err
}
+ } else {
+ // Check custom files.
+ filePath = path.Join(setting.CustomPath, "conf/license", license)
+ if com.IsFile(filePath) {
+ if err := com.Copy(filePath, targetPath); err != nil {
+ return err
+ }
+ }
}
}
@@ -515,17 +454,156 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep
return initRepoCommit(tmpDir, user.NewGitSig())
}
+// CreateRepository creates a repository for given user or organization.
+func CreateRepository(u *User, name, desc, lang, license string, private, mirror, initReadme bool) (*Repository, error) {
+ if !IsLegalName(name) {
+ return nil, ErrRepoNameIllegal
+ }
+
+ isExist, err := IsRepositoryExist(u, name)
+ if err != nil {
+ return nil, err
+ } else if isExist {
+ return nil, ErrRepoAlreadyExist
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err = sess.Begin(); err != nil {
+ return nil, err
+ }
+
+ repo := &Repository{
+ OwnerId: u.Id,
+ Owner: u,
+ Name: name,
+ LowerName: strings.ToLower(name),
+ Description: desc,
+ IsPrivate: private,
+ IsBare: lang == "" && license == "" && !initReadme,
+ }
+ if !repo.IsBare {
+ repo.DefaultBranch = "master"
+ }
+
+ if _, err = sess.Insert(repo); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ var t *Team // Owner team.
+
+ mode := WRITABLE
+ if mirror {
+ mode = READABLE
+ }
+ access := &Access{
+ UserName: u.LowerName,
+ RepoName: strings.ToLower(path.Join(u.Name, repo.Name)),
+ Mode: mode,
+ }
+ // Give access to all members in owner team.
+ if u.IsOrganization() {
+ t, err = u.GetOwnerTeam()
+ if err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+ us, err := GetTeamMembers(u.Id, t.Id)
+ if err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+ for _, u := range us {
+ access.UserName = u.LowerName
+ if _, err = sess.Insert(access); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+ }
+ } else {
+ if _, err = sess.Insert(access); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+ }
+
+ rawSql := "UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?"
+ if _, err = sess.Exec(rawSql, u.Id); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ // Update owner team info and count.
+ if u.IsOrganization() {
+ t.RepoIds += "$" + base.ToStr(repo.Id) + "|"
+ t.NumRepos++
+ if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+ }
+
+ if err = sess.Commit(); err != nil {
+ return nil, err
+ }
+
+ if u.IsOrganization() {
+ ous, err := GetOrgUsersByOrgId(u.Id)
+ if err != nil {
+ log.Error("repo.CreateRepository(GetOrgUsersByOrgId): %v", err)
+ } else {
+ for _, ou := range ous {
+ if err = WatchRepo(ou.Uid, repo.Id, true); err != nil {
+ log.Error("repo.CreateRepository(WatchRepo): %v", err)
+ }
+ }
+ }
+ }
+ if err = WatchRepo(u.Id, repo.Id, true); err != nil {
+ log.Error("repo.CreateRepository(WatchRepo2): %v", err)
+ }
+
+ if err = NewRepoAction(u, repo); err != nil {
+ log.Error("repo.CreateRepository(NewRepoAction): %v", err)
+ }
+
+ // No need for init for mirror.
+ if mirror {
+ return repo, nil
+ }
+
+ repoPath := RepoPath(u.Name, repo.Name)
+ if err = initRepository(repoPath, u, repo, initReadme, lang, license); err != nil {
+ if err2 := os.RemoveAll(repoPath); err2 != nil {
+ log.Error("repo.CreateRepository(initRepository): %v", err)
+ return nil, errors.New(fmt.Sprintf(
+ "delete repo directory %s/%s failed(2): %v", u.Name, repo.Name, err2))
+ }
+ return nil, err
+ }
+
+ _, stderr, err := process.ExecDir(
+ repoPath, fmt.Sprintf("CreateRepository(git update-server-info): %s", repoPath),
+ "git", "update-server-info")
+ if err != nil {
+ return nil, errors.New("CreateRepository(git update-server-info): " + stderr)
+ }
+
+ return repo, nil
+}
+
// GetRepositoriesWithUsers returns given number of repository objects with offset.
// It also auto-gets corresponding users.
func GetRepositoriesWithUsers(num, offset int) ([]*Repository, error) {
repos := make([]*Repository, 0, num)
- if err := orm.Limit(num, offset).Asc("id").Find(&repos); err != nil {
+ if err := x.Limit(num, offset).Asc("id").Find(&repos); err != nil {
return nil, err
}
for _, repo := range repos {
repo.Owner = &User{Id: repo.OwnerId}
- has, err := orm.Get(repo.Owner)
+ has, err := x.Get(repo.Owner)
if err != nil {
return nil, err
} else if !has {
@@ -550,11 +628,11 @@ func TransferOwnership(user *User, newOwner string, repo *Repository) (err error
// Update accesses.
accesses := make([]Access, 0, 10)
- if err = orm.Find(&accesses, &Access{RepoName: user.LowerName + "/" + repo.LowerName}); err != nil {
+ if err = x.Find(&accesses, &Access{RepoName: user.LowerName + "/" + repo.LowerName}); err != nil {
return err
}
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
@@ -615,11 +693,11 @@ func TransferOwnership(user *User, newOwner string, repo *Repository) (err error
func ChangeRepositoryName(userName, oldRepoName, newRepoName string) (err error) {
// Update accesses.
accesses := make([]Access, 0, 10)
- if err = orm.Find(&accesses, &Access{RepoName: strings.ToLower(userName + "/" + oldRepoName)}); err != nil {
+ if err = x.Find(&accesses, &Access{RepoName: strings.ToLower(userName + "/" + oldRepoName)}); err != nil {
return err
}
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
@@ -650,25 +728,26 @@ func UpdateRepository(repo *Repository) error {
if len(repo.Website) > 255 {
repo.Website = repo.Website[:255]
}
- _, err := orm.Id(repo.Id).AllCols().Update(repo)
+ _, err := x.Id(repo.Id).AllCols().Update(repo)
return err
}
// DeleteRepository deletes a repository for a user or orgnaztion.
-func DeleteRepository(userId, repoId int64, userName string) (err error) {
+func DeleteRepository(userId, repoId int64, userName string) error {
repo := &Repository{Id: repoId, OwnerId: userId}
- has, err := orm.Get(repo)
+ has, err := x.Get(repo)
if err != nil {
return err
} else if !has {
return ErrRepoNotExist
}
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
}
+
if _, err = sess.Delete(&Repository{Id: repoId}); err != nil {
sess.Rollback()
return err
@@ -703,7 +782,7 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) {
}
// Delete comments.
- if err = orm.Iterate(&Issue{RepoId: repoId}, func(idx int, bean interface{}) error {
+ if err = x.Iterate(&Issue{RepoId: repoId}, func(idx int, bean interface{}) error {
issue := bean.(*Issue)
if _, err = sess.Delete(&Comment{IssueId: issue.Id}); err != nil {
sess.Rollback()
@@ -725,16 +804,11 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) {
sess.Rollback()
return err
}
- if err = sess.Commit(); err != nil {
- sess.Rollback()
- return err
- }
if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil {
- // TODO: log and delete manully
- log.Error("delete repo %s/%s failed: %v", userName, repo.Name, err)
+ sess.Rollback()
return err
}
- return nil
+ return sess.Commit()
}
// GetRepositoryByName returns the repository by given name under user if exists.
@@ -743,7 +817,7 @@ func GetRepositoryByName(userId int64, repoName string) (*Repository, error) {
OwnerId: userId,
LowerName: strings.ToLower(repoName),
}
- has, err := orm.Get(repo)
+ has, err := x.Get(repo)
if err != nil {
return nil, err
} else if !has {
@@ -755,7 +829,7 @@ func GetRepositoryByName(userId int64, repoName string) (*Repository, error) {
// GetRepositoryById returns the repository by given id if exists.
func GetRepositoryById(id int64) (*Repository, error) {
repo := &Repository{}
- has, err := orm.Id(id).Get(repo)
+ has, err := x.Id(id).Get(repo)
if err != nil {
return nil, err
} else if !has {
@@ -767,7 +841,7 @@ func GetRepositoryById(id int64) (*Repository, error) {
// GetRepositories returns a list of repositories of given user.
func GetRepositories(uid int64, private bool) ([]*Repository, error) {
repos := make([]*Repository, 0, 10)
- sess := orm.Desc("updated")
+ sess := x.Desc("updated")
if !private {
sess.Where("is_private=?", false)
}
@@ -778,19 +852,19 @@ func GetRepositories(uid int64, private bool) ([]*Repository, error) {
// GetRecentUpdatedRepositories returns the list of repositories that are recently updated.
func GetRecentUpdatedRepositories() (repos []*Repository, err error) {
- err = orm.Where("is_private=?", false).Limit(5).Desc("updated").Find(&repos)
+ err = x.Where("is_private=?", false).Limit(5).Desc("updated").Find(&repos)
return repos, err
}
// GetRepositoryCount returns the total number of repositories of user.
func GetRepositoryCount(user *User) (int64, error) {
- return orm.Count(&Repository{OwnerId: user.Id})
+ return x.Count(&Repository{OwnerId: user.Id})
}
// GetCollaboratorNames returns a list of user name of repository's collaborators.
func GetCollaboratorNames(repoName string) ([]string, error) {
accesses := make([]*Access, 0, 10)
- if err := orm.Find(&accesses, &Access{RepoName: strings.ToLower(repoName)}); err != nil {
+ if err := x.Find(&accesses, &Access{RepoName: strings.ToLower(repoName)}); err != nil {
return nil, err
}
@@ -805,17 +879,17 @@ func GetCollaboratorNames(repoName string) ([]string, error) {
func GetCollaborativeRepos(uname string) ([]*Repository, error) {
uname = strings.ToLower(uname)
accesses := make([]*Access, 0, 10)
- if err := orm.Find(&accesses, &Access{UserName: uname}); err != nil {
+ if err := x.Find(&accesses, &Access{UserName: uname}); err != nil {
return nil, err
}
repos := make([]*Repository, 0, 10)
for _, access := range accesses {
- if strings.HasPrefix(access.RepoName, uname) {
+ infos := strings.Split(access.RepoName, "/")
+ if infos[0] == uname {
continue
}
- infos := strings.Split(access.RepoName, "/")
u, err := GetUserByName(infos[0])
if err != nil {
return nil, err
@@ -834,7 +908,7 @@ func GetCollaborativeRepos(uname string) ([]*Repository, error) {
// GetCollaborators returns a list of users of repository's collaborators.
func GetCollaborators(repoName string) (us []*User, err error) {
accesses := make([]*Access, 0, 10)
- if err = orm.Find(&accesses, &Access{RepoName: strings.ToLower(repoName)}); err != nil {
+ if err = x.Find(&accesses, &Access{RepoName: strings.ToLower(repoName)}); err != nil {
return nil, err
}
@@ -858,18 +932,18 @@ type Watch struct {
// Watch or unwatch repository.
func WatchRepo(uid, rid int64, watch bool) (err error) {
if watch {
- if _, err = orm.Insert(&Watch{RepoId: rid, UserId: uid}); err != nil {
+ if _, err = x.Insert(&Watch{RepoId: rid, UserId: uid}); err != nil {
return err
}
rawSql := "UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?"
- _, err = orm.Exec(rawSql, rid)
+ _, err = x.Exec(rawSql, rid)
} else {
- if _, err = orm.Delete(&Watch{0, uid, rid}); err != nil {
+ if _, err = x.Delete(&Watch{0, uid, rid}); err != nil {
return err
}
rawSql := "UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?"
- _, err = orm.Exec(rawSql, rid)
+ _, err = x.Exec(rawSql, rid)
}
return err
}
@@ -877,7 +951,7 @@ func WatchRepo(uid, rid int64, watch bool) (err error) {
// GetWatchers returns all watchers of given repository.
func GetWatchers(rid int64) ([]*Watch, error) {
watches := make([]*Watch, 0, 10)
- err := orm.Find(&watches, &Watch{RepoId: rid})
+ err := x.Find(&watches, &Watch{RepoId: rid})
return watches, err
}
@@ -891,7 +965,7 @@ func NotifyWatchers(act *Action) error {
// Add feed for actioner.
act.UserId = act.ActUserId
- if _, err = orm.InsertOne(act); err != nil {
+ if _, err = x.InsertOne(act); err != nil {
return errors.New("repo.NotifyWatchers(create action): " + err.Error())
}
@@ -902,7 +976,7 @@ func NotifyWatchers(act *Action) error {
act.Id = 0
act.UserId = watches[i].UserId
- if _, err = orm.InsertOne(act); err != nil {
+ if _, err = x.InsertOne(act); err != nil {
return errors.New("repo.NotifyWatchers(create action): " + err.Error())
}
}
@@ -911,7 +985,7 @@ func NotifyWatchers(act *Action) error {
// IsWatching checks if user has watched given repository.
func IsWatching(uid, rid int64) bool {
- has, _ := orm.Get(&Watch{0, uid, rid})
+ has, _ := x.Get(&Watch{0, uid, rid})
return has
}
diff --git a/models/update.go b/models/update.go
index b7242cde..3328f221 100644
--- a/models/update.go
+++ b/models/update.go
@@ -6,21 +6,21 @@ package models
import (
"container/list"
+ "fmt"
"os/exec"
"strings"
- qlog "github.com/qiniu/log"
-
"github.com/gogits/git"
"github.com/gogits/gogs/modules/base"
+ "github.com/gogits/gogs/modules/log"
)
-func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName string, userId int64) {
+func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName string, userId int64) error {
isNew := strings.HasPrefix(oldCommitId, "0000000")
if isNew &&
strings.HasPrefix(newCommitId, "0000000") {
- qlog.Fatal("old rev and new rev both 000000")
+ return fmt.Errorf("old rev and new rev both 000000")
}
f := RepoPath(repoUserName, repoName)
@@ -31,19 +31,18 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
isDel := strings.HasPrefix(newCommitId, "0000000")
if isDel {
- qlog.Info("del rev", refName, "from", userName+"/"+repoName+".git", "by", userId)
- return
+ log.GitLogger.Info("del rev", refName, "from", userName+"/"+repoName+".git", "by", userId)
+ return nil
}
repo, err := git.OpenRepository(f)
if err != nil {
- qlog.Fatalf("runUpdate.Open repoId: %v", err)
+ return fmt.Errorf("runUpdate.Open repoId: %v", err)
}
newCommit, err := repo.GetCommit(newCommitId)
if err != nil {
- qlog.Fatalf("runUpdate GetCommit of newCommitId: %v", err)
- return
+ return fmt.Errorf("runUpdate GetCommit of newCommitId: %v", err)
}
var l *list.List
@@ -51,28 +50,27 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
if isNew {
l, err = newCommit.CommitsBefore()
if err != nil {
- qlog.Fatalf("Find CommitsBefore erro: %v", err)
+ return fmt.Errorf("Find CommitsBefore erro: %v", err)
}
} else {
l, err = newCommit.CommitsBeforeUntil(oldCommitId)
if err != nil {
- qlog.Fatalf("Find CommitsBeforeUntil erro: %v", err)
- return
+ return fmt.Errorf("Find CommitsBeforeUntil erro: %v", err)
}
}
if err != nil {
- qlog.Fatalf("runUpdate.Commit repoId: %v", err)
+ return fmt.Errorf("runUpdate.Commit repoId: %v", err)
}
ru, err := GetUserByName(repoUserName)
if err != nil {
- qlog.Fatalf("runUpdate.GetUserByName: %v", err)
+ return fmt.Errorf("runUpdate.GetUserByName: %v", err)
}
repos, err := GetRepositoryByName(ru.Id, repoName)
if err != nil {
- qlog.Fatalf("runUpdate.GetRepositoryByName userId: %v", err)
+ return fmt.Errorf("runUpdate.GetRepositoryByName userId: %v", err)
}
commits := make([]*base.PushCommit, 0)
@@ -96,6 +94,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
//commits = append(commits, []string{lastCommit.Id().String(), lastCommit.Message()})
if err = CommitRepoAction(userId, ru.Id, userName, actEmail,
repos.Id, repoUserName, repoName, refName, &base.PushCommits{l.Len(), commits}); err != nil {
- qlog.Fatalf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
+ return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
}
+ return nil
}
diff --git a/models/user.go b/models/user.go
index f95f303b..9b0bdebe 100644
--- a/models/user.go
+++ b/models/user.go
@@ -21,14 +21,16 @@ import (
"github.com/gogits/gogs/modules/setting"
)
-// User types.
+type UserType int
+
const (
- UT_INDIVIDUAL = iota + 1
- UT_ORGANIZATION
+ INDIVIDUAL UserType = iota // Historic reason to make it starts at 0.
+ ORGANIZATION
)
var (
ErrUserOwnRepos = errors.New("User still have ownership of repositories")
+ ErrUserHasOrgs = errors.New("User still have membership of organization")
ErrUserAlreadyExist = errors.New("User already exist")
ErrUserNotExist = errors.New("User does not exist")
ErrUserNotKeyOwner = errors.New("User does not the owner of public key")
@@ -47,10 +49,11 @@ type User struct {
FullName string
Email string `xorm:"unique not null"`
Passwd string `xorm:"not null"`
- LoginType int
+ LoginType LoginType
LoginSource int64 `xorm:"not null default 0"`
LoginName string
- Type int
+ Type UserType
+ Orgs []*User `xorm:"-"`
NumFollowers int
NumFollowings int
NumStars int
@@ -65,43 +68,63 @@ type User struct {
Salt string `xorm:"VARCHAR(10)"`
Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"`
+
+ // For organization.
+ Description string
+ NumTeams int
+ NumMembers int
}
// HomeLink returns the user home page link.
-func (user *User) HomeLink() string {
- return "/user/" + user.Name
+func (u *User) HomeLink() string {
+ return "/user/" + u.Name
}
-// AvatarLink returns the user gravatar link.
-func (user *User) AvatarLink() string {
+// AvatarLink returns user gravatar link.
+func (u *User) AvatarLink() string {
if setting.DisableGravatar {
return "/img/avatar_default.jpg"
} else if setting.Service.EnableCacheAvatar {
- return "/avatar/" + user.Avatar
+ return "/avatar/" + u.Avatar
}
- return "//1.gravatar.com/avatar/" + user.Avatar
+ return "//1.gravatar.com/avatar/" + u.Avatar
}
// NewGitSig generates and returns the signature of given user.
-func (user *User) NewGitSig() *git.Signature {
+func (u *User) NewGitSig() *git.Signature {
return &git.Signature{
- Name: user.Name,
- Email: user.Email,
+ Name: u.Name,
+ Email: u.Email,
When: time.Now(),
}
}
// EncodePasswd encodes password to safe format.
-func (user *User) EncodePasswd() {
- newPasswd := base.PBKDF2([]byte(user.Passwd), []byte(user.Salt), 10000, 50, sha256.New)
- user.Passwd = fmt.Sprintf("%x", newPasswd)
+func (u *User) EncodePasswd() {
+ newPasswd := base.PBKDF2([]byte(u.Passwd), []byte(u.Salt), 10000, 50, sha256.New)
+ u.Passwd = fmt.Sprintf("%x", newPasswd)
}
-// Member represents user is member of organization.
-type Member struct {
- Id int64
- OrgId int64 `xorm:"unique(member) index"`
- UserId int64 `xorm:"unique(member)"`
+// IsOrganization returns true if user is actually a organization.
+func (u *User) IsOrganization() bool {
+ return u.Type == ORGANIZATION
+}
+
+// GetOrganizations returns all organizations that user belongs to.
+func (u *User) GetOrganizations() error {
+ ous, err := GetOrgUsersByUserId(u.Id)
+ if err != nil {
+ return err
+ }
+
+ u.Orgs = make([]*User, len(ous))
+ for i, ou := range ous {
+ u.Orgs[i], err = GetUserById(ou.OrgId)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
}
// IsUserExist checks if given user name exist,
@@ -110,7 +133,7 @@ func IsUserExist(name string) (bool, error) {
if len(name) == 0 {
return false, nil
}
- return orm.Get(&User{LowerName: strings.ToLower(name)})
+ return x.Get(&User{LowerName: strings.ToLower(name)})
}
// IsEmailUsed returns true if the e-mail has been used.
@@ -118,7 +141,7 @@ func IsEmailUsed(email string) (bool, error) {
if len(email) == 0 {
return false, nil
}
- return orm.Get(&User{Email: email})
+ return x.Get(&User{Email: email})
}
// GetUserSalt returns a user salt token
@@ -126,55 +149,66 @@ func GetUserSalt() string {
return base.GetRandomString(10)
}
-// RegisterUser creates record of a new user.
-func RegisterUser(user *User) (*User, error) {
-
- if !IsLegalName(user.Name) {
+// CreateUser creates record of a new user.
+func CreateUser(u *User) (*User, error) {
+ if !IsLegalName(u.Name) {
return nil, ErrUserNameIllegal
}
- isExist, err := IsUserExist(user.Name)
+ isExist, err := IsUserExist(u.Name)
if err != nil {
return nil, err
} else if isExist {
return nil, ErrUserAlreadyExist
}
- isExist, err = IsEmailUsed(user.Email)
+ isExist, err = IsEmailUsed(u.Email)
if err != nil {
return nil, err
} else if isExist {
return nil, ErrEmailAlreadyUsed
}
- user.LowerName = strings.ToLower(user.Name)
- user.Avatar = base.EncodeMd5(user.Email)
- user.AvatarEmail = user.Email
- user.Rands = GetUserSalt()
- user.Salt = GetUserSalt()
- user.EncodePasswd()
- if _, err = orm.Insert(user); err != nil {
+ u.LowerName = strings.ToLower(u.Name)
+ u.Avatar = base.EncodeMd5(u.Email)
+ u.AvatarEmail = u.Email
+ u.Rands = GetUserSalt()
+ u.Salt = GetUserSalt()
+ u.EncodePasswd()
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err = sess.Begin(); err != nil {
return nil, err
- } else if err = os.MkdirAll(UserPath(user.Name), os.ModePerm); err != nil {
- if _, err := orm.Id(user.Id).Delete(&User{}); err != nil {
- return nil, errors.New(fmt.Sprintf(
- "both create userpath %s and delete table record faild: %v", user.Name, err))
- }
+ }
+
+ if _, err = sess.Insert(u); err != nil {
+ sess.Rollback()
return nil, err
}
- if user.Id == 1 {
- user.IsAdmin = true
- user.IsActive = true
- _, err = orm.Id(user.Id).UseBool().Update(user)
+ if err = os.MkdirAll(UserPath(u.Name), os.ModePerm); err != nil {
+ sess.Rollback()
+ return nil, err
}
- return user, err
+
+ if err = sess.Commit(); err != nil {
+ return nil, err
+ }
+
+ // Auto-set admin for user whose ID is 1.
+ if u.Id == 1 {
+ u.IsAdmin = true
+ u.IsActive = true
+ _, err = x.Id(u.Id).UseBool().Update(u)
+ }
+ return u, err
}
// GetUsers returns given number of user objects with offset.
func GetUsers(num, offset int) ([]User, error) {
users := make([]User, 0, num)
- err := orm.Limit(num, offset).Asc("id").Find(&users)
+ err := x.Limit(num, offset).Asc("id").Find(&users)
return users, err
}
@@ -218,11 +252,11 @@ func ChangeUserName(user *User, newUserName string) (err error) {
// Update accesses of user.
accesses := make([]Access, 0, 10)
- if err = orm.Find(&accesses, &Access{UserName: user.LowerName}); err != nil {
+ if err = x.Find(&accesses, &Access{UserName: user.LowerName}); err != nil {
return err
}
- sess := orm.NewSession()
+ sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
@@ -245,7 +279,7 @@ func ChangeUserName(user *User, newUserName string) (err error) {
for i := range repos {
accesses = make([]Access, 0, 10)
// Update accesses of user repository.
- if err = orm.Find(&accesses, &Access{RepoName: user.LowerName + "/" + repos[i].LowerName}); err != nil {
+ if err = x.Find(&accesses, &Access{RepoName: user.LowerName + "/" + repos[i].LowerName}); err != nil {
return err
}
@@ -268,60 +302,68 @@ func ChangeUserName(user *User, newUserName string) (err error) {
}
// UpdateUser updates user's information.
-func UpdateUser(user *User) (err error) {
- user.LowerName = strings.ToLower(user.Name)
+func UpdateUser(u *User) (err error) {
+ u.LowerName = strings.ToLower(u.Name)
- if len(user.Location) > 255 {
- user.Location = user.Location[:255]
+ if len(u.Location) > 255 {
+ u.Location = u.Location[:255]
+ }
+ if len(u.Website) > 255 {
+ u.Website = u.Website[:255]
}
- if len(user.Website) > 255 {
- user.Website = user.Website[:255]
+ if len(u.Description) > 255 {
+ u.Description = u.Description[:255]
}
- _, err = orm.Id(user.Id).AllCols().Update(user)
+ _, err = x.Id(u.Id).AllCols().Update(u)
return err
}
-// DeleteUser completely deletes everything of the user.
-func DeleteUser(user *User) error {
+// TODO: need some kind of mechanism to record failure.
+// DeleteUser completely and permanently deletes everything of user.
+func DeleteUser(u *User) error {
// Check ownership of repository.
- count, err := GetRepositoryCount(user)
+ count, err := GetRepositoryCount(u)
if err != nil {
- return errors.New("modesl.GetRepositories: " + err.Error())
+ return errors.New("modesl.GetRepositories(GetRepositoryCount): " + err.Error())
} else if count > 0 {
return ErrUserOwnRepos
}
+ // Check membership of organization.
+ count, err = GetOrganizationCount(u)
+ if err != nil {
+ return errors.New("modesl.GetRepositories(GetOrganizationCount): " + err.Error())
+ } else if count > 0 {
+ return ErrUserHasOrgs
+ }
+
// TODO: check issues, other repos' commits
+ // TODO: roll backable in some point.
// Delete all followers.
- if _, err = orm.Delete(&Follow{FollowId: user.Id}); err != nil {
+ if _, err = x.Delete(&Follow{FollowId: u.Id}); err != nil {
return err
}
-
// Delete oauth2.
- if _, err = orm.Delete(&Oauth2{Uid: user.Id}); err != nil {
+ if _, err = x.Delete(&Oauth2{Uid: u.Id}); err != nil {
return err
}
-
// Delete all feeds.
- if _, err = orm.Delete(&Action{UserId: user.Id}); err != nil {
+ if _, err = x.Delete(&Action{UserId: u.Id}); err != nil {
return err
}
-
// Delete all watches.
- if _, err = orm.Delete(&Watch{UserId: user.Id}); err != nil {
+ if _, err = x.Delete(&Watch{UserId: u.Id}); err != nil {
return err
}
-
// Delete all accesses.
- if _, err = orm.Delete(&Access{UserName: user.LowerName}); err != nil {
+ if _, err = x.Delete(&Access{UserName: u.LowerName}); err != nil {
return err
}
-
// Delete all SSH keys.
keys := make([]*PublicKey, 0, 10)
- if err = orm.Find(&keys, &PublicKey{OwnerId: user.Id}); err != nil {
+ if err = x.Find(&keys, &PublicKey{OwnerId: u.Id}); err != nil {
return err
}
for _, key := range keys {
@@ -331,11 +373,17 @@ func DeleteUser(user *User) error {
}
// Delete user directory.
- if err = os.RemoveAll(UserPath(user.Name)); err != nil {
+ if err = os.RemoveAll(UserPath(u.Name)); err != nil {
return err
}
- _, err = orm.Delete(user)
+ _, err = x.Delete(u)
+ return err
+}
+
+// DeleteInactivateUsers deletes all inactivate users.
+func DeleteInactivateUsers() error {
+ _, err := x.Where("is_active=?", false).Delete(new(User))
return err
}
@@ -347,7 +395,7 @@ func UserPath(userName string) string {
func GetUserByKeyId(keyId int64) (*User, error) {
user := new(User)
rawSql := "SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?"
- has, err := orm.Sql(rawSql, keyId).Get(user)
+ has, err := x.Sql(rawSql, keyId).Get(user)
if err != nil {
return nil, err
} else if !has {
@@ -356,17 +404,16 @@ func GetUserByKeyId(keyId int64) (*User, error) {
return user, nil
}
-// GetUserById returns the user object by given id if exists.
+// GetUserById returns the user object by given ID if exists.
func GetUserById(id int64) (*User, error) {
- user := new(User)
- has, err := orm.Id(id).Get(user)
+ u := new(User)
+ has, err := x.Id(id).Get(u)
if err != nil {
return nil, err
- }
- if !has {
+ } else if !has {
return nil, ErrUserNotExist
}
- return user, nil
+ return u, nil
}
// GetUserByName returns the user object by given name if exists.
@@ -375,7 +422,7 @@ func GetUserByName(name string) (*User, error) {
return nil, ErrUserNotExist
}
user := &User{LowerName: strings.ToLower(name)}
- has, err := orm.Get(user)
+ has, err := x.Get(user)
if err != nil {
return nil, err
} else if !has {
@@ -416,7 +463,7 @@ func GetUserByEmail(email string) (*User, error) {
return nil, ErrUserNotExist
}
user := &User{Email: strings.ToLower(email)}
- has, err := orm.Get(user)
+ has, err := x.Get(user)
if err != nil {
return nil, err
} else if !has {
@@ -440,7 +487,7 @@ func SearchUserByName(key string, limit int) (us []*User, err error) {
key = strings.ToLower(key)
us = make([]*User, 0, limit)
- err = orm.Limit(limit).Where("lower_name like '%" + key + "%'").Find(&us)
+ err = x.Limit(limit).Where("lower_name like '%" + key + "%'").Find(&us)
return us, err
}
@@ -453,7 +500,7 @@ type Follow struct {
// FollowUser marks someone be another's follower.
func FollowUser(userId int64, followId int64) (err error) {
- session := orm.NewSession()
+ session := x.NewSession()
defer session.Close()
session.Begin()
@@ -478,7 +525,7 @@ func FollowUser(userId int64, followId int64) (err error) {
// UnFollowUser unmarks someone be another's follower.
func UnFollowUser(userId int64, unFollowId int64) (err error) {
- session := orm.NewSession()
+ session := x.NewSession()
defer session.Close()
session.Begin()
diff --git a/models/webhook.go b/models/webhook.go
index f10fa213..9044befb 100644
--- a/models/webhook.go
+++ b/models/webhook.go
@@ -7,29 +7,35 @@ package models
import (
"encoding/json"
"errors"
+ "time"
+ "github.com/gogits/gogs/modules/httplib"
"github.com/gogits/gogs/modules/log"
+ "github.com/gogits/gogs/modules/setting"
)
var (
ErrWebhookNotExist = errors.New("Webhook does not exist")
)
-// Content types.
+type HookContentType int
+
const (
- CT_JSON = iota + 1
- CT_FORM
+ JSON HookContentType = iota + 1
+ FORM
)
+// HookEvent represents events that will delivery hook.
type HookEvent struct {
PushOnly bool `json:"push_only"`
}
+// Webhook represents a web hook object.
type Webhook struct {
Id int64
RepoId int64
Url string `xorm:"TEXT"`
- ContentType int
+ ContentType HookContentType
Secret string `xorm:"TEXT"`
Events string `xorm:"TEXT"`
*HookEvent `xorm:"-"`
@@ -37,6 +43,7 @@ type Webhook struct {
IsActive bool
}
+// GetEvent handles conversion from Events to HookEvent.
func (w *Webhook) GetEvent() {
w.HookEvent = &HookEvent{}
if err := json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil {
@@ -44,12 +51,14 @@ func (w *Webhook) GetEvent() {
}
}
-func (w *Webhook) SaveEvent() error {
+// UpdateEvent handles conversion from HookEvent to Events.
+func (w *Webhook) UpdateEvent() error {
data, err := json.Marshal(w.HookEvent)
w.Events = string(data)
return err
}
+// HasPushEvent returns true if hook enbaled push event.
func (w *Webhook) HasPushEvent() bool {
if w.PushOnly {
return true
@@ -57,22 +66,16 @@ func (w *Webhook) HasPushEvent() bool {
return false
}
-// CreateWebhook creates new webhook.
+// CreateWebhook creates a new web hook.
func CreateWebhook(w *Webhook) error {
- _, err := orm.Insert(w)
- return err
-}
-
-// UpdateWebhook updates information of webhook.
-func UpdateWebhook(w *Webhook) error {
- _, err := orm.AllCols().Update(w)
+ _, err := x.Insert(w)
return err
}
// GetWebhookById returns webhook by given ID.
func GetWebhookById(hookId int64) (*Webhook, error) {
w := &Webhook{Id: hookId}
- has, err := orm.Get(w)
+ has, err := x.Get(w)
if err != nil {
return nil, err
} else if !has {
@@ -83,18 +86,124 @@ func GetWebhookById(hookId int64) (*Webhook, error) {
// GetActiveWebhooksByRepoId returns all active webhooks of repository.
func GetActiveWebhooksByRepoId(repoId int64) (ws []*Webhook, err error) {
- err = orm.Find(&ws, &Webhook{RepoId: repoId, IsActive: true})
+ err = x.Find(&ws, &Webhook{RepoId: repoId, IsActive: true})
return ws, err
}
// GetWebhooksByRepoId returns all webhooks of repository.
func GetWebhooksByRepoId(repoId int64) (ws []*Webhook, err error) {
- err = orm.Find(&ws, &Webhook{RepoId: repoId})
+ err = x.Find(&ws, &Webhook{RepoId: repoId})
return ws, err
}
+// UpdateWebhook updates information of webhook.
+func UpdateWebhook(w *Webhook) error {
+ _, err := x.AllCols().Update(w)
+ return err
+}
+
// DeleteWebhook deletes webhook of repository.
func DeleteWebhook(hookId int64) error {
- _, err := orm.Delete(&Webhook{Id: hookId})
+ _, err := x.Delete(&Webhook{Id: hookId})
+ return err
+}
+
+// ___ ___ __ ___________ __
+// / | \ ____ ____ | | _\__ ___/____ _____| | __
+// / ~ \/ _ \ / _ \| |/ / | | \__ \ / ___/ |/ /
+// \ Y ( <_> | <_> ) < | | / __ \_\___ \| <
+// \___|_ / \____/ \____/|__|_ \ |____| (____ /____ >__|_ \
+// \/ \/ \/ \/ \/
+
+type HookTaskType int
+
+const (
+ WEBHOOK HookTaskType = iota + 1
+ SERVICE
+)
+
+type PayloadAuthor struct {
+ Name string `json:"name"`
+ Email string `json:"email"`
+}
+
+type PayloadCommit struct {
+ Id string `json:"id"`
+ Message string `json:"message"`
+ Url string `json:"url"`
+ Author *PayloadAuthor `json:"author"`
+}
+
+type PayloadRepo struct {
+ Id int64 `json:"id"`
+ Name string `json:"name"`
+ Url string `json:"url"`
+ Description string `json:"description"`
+ Website string `json:"website"`
+ Watchers int `json:"watchers"`
+ Owner *PayloadAuthor `json:"author"`
+ Private bool `json:"private"`
+}
+
+// Payload represents a payload information of hook.
+type Payload struct {
+ Secret string `json:"secret"`
+ Ref string `json:"ref"`
+ Commits []*PayloadCommit `json:"commits"`
+ Repo *PayloadRepo `json:"repository"`
+ Pusher *PayloadAuthor `json:"pusher"`
+}
+
+// HookTask represents a hook task.
+type HookTask struct {
+ Id int64
+ Type HookTaskType
+ Url string
+ *Payload `xorm:"-"`
+ PayloadContent string `xorm:"TEXT"`
+ ContentType HookContentType
+ IsSsl bool
+ IsDeliveried bool
+}
+
+// CreateHookTask creates a new hook task,
+// it handles conversion from Payload to PayloadContent.
+func CreateHookTask(t *HookTask) error {
+ data, err := json.Marshal(t.Payload)
+ if err != nil {
+ return err
+ }
+ t.PayloadContent = string(data)
+ _, err = x.Insert(t)
return err
}
+
+// UpdateHookTask updates information of hook task.
+func UpdateHookTask(t *HookTask) error {
+ _, err := x.AllCols().Update(t)
+ return err
+}
+
+// DeliverHooks checks and delivers undelivered hooks.
+func DeliverHooks() {
+ timeout := time.Duration(setting.WebhookDeliverTimeout) * time.Second
+ x.Where("is_deliveried=?", false).Iterate(new(HookTask),
+ func(idx int, bean interface{}) error {
+ t := bean.(*HookTask)
+ // Only support JSON now.
+ if _, err := httplib.Post(t.Url).SetTimeout(timeout, timeout).
+ Body([]byte(t.PayloadContent)).Response(); err != nil {
+ log.Error("webhook.DeliverHooks(Delivery): %v", err)
+ return nil
+ }
+
+ t.IsDeliveried = true
+ if err := UpdateHookTask(t); err != nil {
+ log.Error("webhook.DeliverHooks(UpdateHookTask): %v", err)
+ return nil
+ }
+
+ log.Trace("Hook delivered: %s", t.PayloadContent)
+ return nil
+ })
+}