Browse Source

v4 migration, merge 'dev', clean code and mirror fix

Unknwon 10 năm trước cách đây
mục cha
commit
ee68a826a5
11 tập tin đã thay đổi với 343 bổ sung234 xóa
  1. 1 1
      gogs.go
  2. 23 14
      models/access.go
  3. 10 10
      models/action.go
  4. 64 12
      models/migrations/migrations.go
  5. 3 2
      models/models.go
  6. 181 115
      models/org.go
  7. 57 75
      models/repo.go
  8. 2 2
      models/user.go
  9. 1 1
      routers/org/teams.go
  10. 0 1
      routers/repo/setting.go
  11. 1 1
      templates/.VERSION

+ 1 - 1
gogs.go

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

+ 23 - 14
models/access.go

@@ -24,21 +24,19 @@ type Access struct {
 	Mode   AccessMode
 }
 
-// Return the Access a user has to a repository. Will return NoneAccess if the
-// user does not have access. User can be nil!
-func AccessLevel(u *User, r *Repository) (AccessMode, error) {
+func accessLevel(e Engine, u *User, repo *Repository) (AccessMode, error) {
 	mode := ACCESS_MODE_NONE
-	if !r.IsPrivate {
+	if !repo.IsPrivate {
 		mode = ACCESS_MODE_READ
 	}
 
 	if u != nil {
-		if u.Id == r.OwnerId {
+		if u.Id == repo.OwnerId {
 			return ACCESS_MODE_OWNER, nil
 		}
 
-		a := &Access{UserID: u.Id, RepoID: r.Id}
-		if has, err := x.Get(a); !has || err != nil {
+		a := &Access{UserID: u.Id, RepoID: repo.Id}
+		if has, err := e.Get(a); !has || err != nil {
 			return mode, err
 		}
 		return a.Mode, nil
@@ -47,12 +45,22 @@ func AccessLevel(u *User, r *Repository) (AccessMode, error) {
 	return mode, nil
 }
 
-// HasAccess returns true if someone has the request access level. User can be nil!
-func HasAccess(u *User, r *Repository, testMode AccessMode) (bool, error) {
-	mode, err := AccessLevel(u, r)
+// AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the
+// user does not have access. User can be nil!
+func AccessLevel(u *User, repo *Repository) (AccessMode, error) {
+	return accessLevel(x, u, repo)
+}
+
+func hasAccess(e Engine, u *User, repo *Repository, testMode AccessMode) (bool, error) {
+	mode, err := accessLevel(e, u, repo)
 	return testMode <= mode, err
 }
 
+// HasAccess returns true if someone has the request access level. User can be nil!
+func HasAccess(u *User, repo *Repository, testMode AccessMode) (bool, error) {
+	return hasAccess(x, u, repo, testMode)
+}
+
 // GetAccessibleRepositories finds all repositories where a user has access to,
 // besides his own.
 func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) {
@@ -96,7 +104,8 @@ func (repo *Repository) recalculateTeamAccesses(e Engine, mode AccessMode) error
 func (repo *Repository) recalculateAccesses(e Engine) error {
 	accessMap := make(map[int64]AccessMode, 20)
 
-	// Give all collaborators write access
+	// FIXME: should be able to have read-only access.
+	// Give all collaborators write access.
 	collaborators, err := repo.getCollaborators(e)
 	if err != nil {
 		return err
@@ -114,9 +123,7 @@ func (repo *Repository) recalculateAccesses(e Engine) error {
 		}
 
 		for _, team := range repo.Owner.Teams {
-			if !(team.IsOwnerTeam() || team.HasRepository(repo)) {
-				continue
-			} else if team.IsOwnerTeam() {
+			if team.IsOwnerTeam() {
 				team.Authorize = ACCESS_MODE_OWNER
 			}
 
@@ -129,6 +136,8 @@ func (repo *Repository) recalculateAccesses(e Engine) error {
 		}
 	}
 
+	// FIXME: do corss-comparison so reduce deletions and additions to the minimum?
+
 	minMode := ACCESS_MODE_READ
 	if !repo.IsPrivate {
 		minMode = ACCESS_MODE_WRITE

+ 10 - 10
models/action.go

@@ -434,20 +434,20 @@ func NewRepoAction(u *User, repo *Repository) (err error) {
 	return newRepoAction(x, u, repo)
 }
 
-func transferRepoAction(e Engine, u, newUser *User, repo *Repository) (err error) {
+func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repository) (err error) {
 	action := &Action{
-		ActUserId:    u.Id,
-		ActUserName:  u.Name,
-		ActEmail:     u.Email,
+		ActUserId:    actUser.Id,
+		ActUserName:  actUser.Name,
+		ActEmail:     actUser.Email,
 		OpType:       TRANSFER_REPO,
 		RepoId:       repo.Id,
-		RepoUserName: newUser.Name,
+		RepoUserName: newOwner.Name,
 		RepoName:     repo.Name,
 		IsPrivate:    repo.IsPrivate,
-		Content:      path.Join(repo.Owner.LowerName, repo.LowerName),
+		Content:      path.Join(oldOwner.LowerName, repo.LowerName),
 	}
 	if err = notifyWatchers(e, action); err != nil {
-		return fmt.Errorf("notify watchers '%d/%s'", u.Id, repo.Id)
+		return fmt.Errorf("notify watchers '%d/%s'", actUser.Id, repo.Id)
 	}
 
 	// Remove watch for organization.
@@ -457,13 +457,13 @@ func transferRepoAction(e Engine, u, newUser *User, repo *Repository) (err error
 		}
 	}
 
-	log.Trace("action.TransferRepoAction: %s/%s", u.Name, repo.Name)
+	log.Trace("action.TransferRepoAction: %s/%s", actUser.Name, repo.Name)
 	return nil
 }
 
 // TransferRepoAction adds new action for transferring repository.
-func TransferRepoAction(u, newUser *User, repo *Repository) (err error) {
-	return transferRepoAction(x, u, newUser, repo)
+func TransferRepoAction(actUser, oldOwner, newOwner *User, repo *Repository) (err error) {
+	return transferRepoAction(x, actUser, oldOwner, newOwner, repo)
 }
 
 // GetFeeds returns action list of given user in given context.

+ 64 - 12
models/migrations/migrations.go

@@ -53,6 +53,7 @@ var migrations = []Migration{
 	NewMigration("generate collaboration from access", accessToCollaboration), // V0 -> V1
 	NewMigration("make authorize 4 if team is owners", ownerTeamUpdate),       // V1 -> V2
 	NewMigration("refactor access table to use id's", accessRefactor),         // V2 -> V3
+	NewMigration("generate team-repo from team", teamToTeamRepo),              // V3 -> V4
 }
 
 // Migrate database to current version
@@ -214,8 +215,8 @@ func accessToCollaboration(x *xorm.Engine) (err error) {
 }
 
 func ownerTeamUpdate(x *xorm.Engine) (err error) {
-	if _, err := x.Exec("UPDATE team SET authorize=4 WHERE lower_name=?", "owners"); err != nil {
-		return fmt.Errorf("drop table: %v", err)
+	if _, err := x.Exec("UPDATE `team` SET authorize=4 WHERE lower_name=?", "owners"); err != nil {
+		return fmt.Errorf("update owner team table: %v", err)
 	}
 	return nil
 }
@@ -239,9 +240,9 @@ func accessRefactor(x *xorm.Engine) (err error) {
 
 	accessMap := make(map[UserRepo]AccessMode, 50)
 
-	results, err := x.Query("SELECT r.id as `repo_id`, r.is_private as `is_private`, r.owner_id as `owner_id`, u.type as `owner_type` FROM `repository` r LEFT JOIN user u ON r.owner_id=u.id")
+	results, err := x.Query("SELECT r.id AS `repo_id`, r.is_private AS `is_private`, r.owner_id AS `owner_id`, u.type AS `owner_type` FROM `repository` r LEFT JOIN `user` u ON r.owner_id=u.id")
 	if err != nil {
-		return err
+		return fmt.Errorf("select repositories: %v", err)
 	}
 	for _, repo := range results {
 		repoID := com.StrTo(repo["repo_id"]).MustInt64()
@@ -249,9 +250,9 @@ func accessRefactor(x *xorm.Engine) (err error) {
 		ownerID := com.StrTo(repo["owner_id"]).MustInt64()
 		ownerIsOrganization := com.StrTo(repo["owner_type"]).MustInt() > 0
 
-		results, err := x.Query("SELECT user_id FROM collaboration WHERE repo_id=?", repoID)
+		results, err := x.Query("SELECT `user_id` FROM `collaboration` WHERE repo_id=?", repoID)
 		if err != nil {
-			return fmt.Errorf("select repos: %v", err)
+			return fmt.Errorf("select collaborators: %v", err)
 		}
 		for _, user := range results {
 			userID := com.StrTo(user["user_id"]).MustInt64()
@@ -262,6 +263,8 @@ func accessRefactor(x *xorm.Engine) (err error) {
 			continue
 		}
 
+		// The minimum level to add a new access record,
+		// because public repository has implicit open access.
 		minAccessLevel := AccessMode(0)
 		if !isPrivate {
 			minAccessLevel = 1
@@ -269,7 +272,7 @@ func accessRefactor(x *xorm.Engine) (err error) {
 
 		repoString := "$" + string(repo["repo_id"]) + "|"
 
-		results, err = x.Query("SELECT id, authorize, repo_ids FROM team WHERE org_id=? AND authorize > ? ORDER BY authorize ASC", ownerID, int(minAccessLevel))
+		results, err = x.Query("SELECT `id`,`authorize`,`repo_ids` FROM `team` WHERE org_id=? AND authorize>? ORDER BY `authorize` ASC", ownerID, int(minAccessLevel))
 		if err != nil {
 			return fmt.Errorf("select teams from org: %v", err)
 		}
@@ -281,20 +284,20 @@ func accessRefactor(x *xorm.Engine) (err error) {
 			teamID := com.StrTo(team["id"]).MustInt64()
 			mode := AccessMode(com.StrTo(team["authorize"]).MustInt())
 
-			results, err := x.Query("SELECT uid FROM team_user WHERE team_id=?", teamID)
+			results, err := x.Query("SELECT `uid` FROM `team_user` WHERE team_id=?", teamID)
 			if err != nil {
 				return fmt.Errorf("select users from team: %v", err)
 			}
 			for _, user := range results {
-				userID := com.StrTo(user["uid"]).MustInt64()
+				userID := com.StrTo(user["user_id"]).MustInt64()
 				accessMap[UserRepo{userID, repoID}] = mode
 			}
 		}
 	}
 
 	// Drop table can't be in a session (at least not in sqlite)
-	if _, err = x.Exec("DROP TABLE access"); err != nil {
-		return fmt.Errorf("drop table: %v", err)
+	if _, err = x.Exec("DROP TABLE `access`"); err != nil {
+		return fmt.Errorf("drop access table: %v", err)
 	}
 
 	// Now we start writing so we make a session
@@ -313,7 +316,56 @@ func accessRefactor(x *xorm.Engine) (err error) {
 		accesses = append(accesses, &Access{UserID: ur.UserID, RepoID: ur.RepoID, Mode: mode})
 	}
 
-	_, err = sess.Insert(accesses)
+	if _, err = sess.Insert(accesses); err != nil {
+		return fmt.Errorf("insert accesses: %v", err)
+	}
+
+	return sess.Commit()
+}
+
+func teamToTeamRepo(x *xorm.Engine) error {
+	type TeamRepo struct {
+		ID     int64 `xorm:"pk autoincr"`
+		OrgID  int64 `xorm:"INDEX"`
+		TeamID int64 `xorm:"UNIQUE(s)"`
+		RepoID int64 `xorm:"UNIQUE(s)"`
+	}
+
+	teamRepos := make([]*TeamRepo, 0, 50)
+
+	results, err := x.Query("SELECT `id`,`org_id`,`repo_ids` FROM `team`")
+	if err != nil {
+		return fmt.Errorf("select teams: %v", err)
+	}
+	for _, team := range results {
+		orgID := com.StrTo(team["org_id"]).MustInt64()
+		teamID := com.StrTo(team["id"]).MustInt64()
+
+		for _, idStr := range strings.Split(string(team["repo_ids"]), "|") {
+			repoID := com.StrTo(strings.TrimPrefix(idStr, "$")).MustInt64()
+			if repoID == 0 {
+				continue
+			}
+
+			teamRepos = append(teamRepos, &TeamRepo{
+				OrgID:  orgID,
+				TeamID: teamID,
+				RepoID: repoID,
+			})
+		}
+	}
+
+	sess := x.NewSession()
+	defer sessionRelease(sess)
+	if err = sess.Begin(); err != nil {
+		return err
+	}
+
+	if err = sess.Sync2(new(TeamRepo)); err != nil {
+		return fmt.Errorf("sync: %v", err)
+	} else if _, err = sess.Insert(teamRepos); err != nil {
+		return fmt.Errorf("insert team-repos: %v", err)
+	}
 
 	return sess.Commit()
 }

+ 3 - 2
models/models.go

@@ -16,7 +16,7 @@ import (
 	"github.com/go-xorm/xorm"
 	_ "github.com/lib/pq"
 
-	// "github.com/gogits/gogs/models/migrations"
+	"github.com/gogits/gogs/models/migrations"
 	"github.com/gogits/gogs/modules/setting"
 )
 
@@ -59,7 +59,8 @@ func init() {
 		new(Watch), new(Star), new(Follow), new(Action),
 		new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone),
 		new(Mirror), new(Release), new(LoginSource), new(Webhook),
-		new(UpdateTask), new(HookTask), new(Team), new(OrgUser), new(TeamUser),
+		new(UpdateTask), new(HookTask),
+		new(Team), new(OrgUser), new(TeamUser), new(TeamRepo),
 		new(Notice), new(EmailAddress))
 }
 

+ 181 - 115
models/org.go

@@ -6,11 +6,10 @@ package models
 
 import (
 	"errors"
+	"fmt"
 	"os"
 	"strings"
 
-	"github.com/Unknwon/com"
-
 	"github.com/gogits/gogs/modules/base"
 )
 
@@ -126,53 +125,48 @@ func CreateOrganization(org, owner *User) (*User, error) {
 	org.NumMembers = 1
 
 	sess := x.NewSession()
-	defer sess.Close()
+	defer sessionRelease(sess)
 	if err = sess.Begin(); err != nil {
 		return nil, err
 	}
 
 	if _, err = sess.Insert(org); err != nil {
-		sess.Rollback()
-		return nil, err
-	}
-
-	if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil {
-		sess.Rollback()
 		return nil, err
 	}
 
 	// Create default owner team.
 	t := &Team{
-		OrgId:      org.Id,
+		OrgID:      org.Id,
 		LowerName:  strings.ToLower(OWNER_TEAM),
 		Name:       OWNER_TEAM,
 		Authorize:  ACCESS_MODE_OWNER,
 		NumMembers: 1,
 	}
 	if _, err = sess.Insert(t); err != nil {
-		sess.Rollback()
 		return nil, err
 	}
 
 	// Add initial creator to organization and owner team.
 	ou := &OrgUser{
 		Uid:      owner.Id,
-		OrgId:    org.Id,
+		OrgID:    org.Id,
 		IsOwner:  true,
 		NumTeams: 1,
 	}
 	if _, err = sess.Insert(ou); err != nil {
-		sess.Rollback()
 		return nil, err
 	}
 
 	tu := &TeamUser{
 		Uid:    owner.Id,
-		OrgId:  org.Id,
-		TeamId: t.Id,
+		OrgID:  org.Id,
+		TeamID: t.ID,
 	}
 	if _, err = sess.Insert(tu); err != nil {
-		sess.Rollback()
+		return nil, err
+	}
+
+	if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil {
 		return nil, err
 	}
 
@@ -223,15 +217,15 @@ func DeleteOrganization(org *User) (err error) {
 		return err
 	}
 
-	if _, err = sess.Delete(&Team{OrgId: org.Id}); err != nil {
+	if _, err = sess.Delete(&Team{OrgID: org.Id}); err != nil {
 		sess.Rollback()
 		return err
 	}
-	if _, err = sess.Delete(&OrgUser{OrgId: org.Id}); err != nil {
+	if _, err = sess.Delete(&OrgUser{OrgID: org.Id}); err != nil {
 		sess.Rollback()
 		return err
 	}
-	if _, err = sess.Delete(&TeamUser{OrgId: org.Id}); err != nil {
+	if _, err = sess.Delete(&TeamUser{OrgID: org.Id}); err != nil {
 		sess.Rollback()
 		return err
 	}
@@ -247,9 +241,9 @@ func DeleteOrganization(org *User) (err error) {
 
 // OrgUser represents an organization-user relation.
 type OrgUser struct {
-	Id       int64
+	ID       int64 `xorm:"pk autoincr"`
 	Uid      int64 `xorm:"INDEX UNIQUE(s)"`
-	OrgId    int64 `xorm:"INDEX UNIQUE(s)"`
+	OrgID    int64 `xorm:"INDEX UNIQUE(s)"`
 	IsPublic bool
 	IsOwner  bool
 	NumTeams int
@@ -298,7 +292,7 @@ func ChangeOrgUserStatus(orgId, uid int64, public bool) error {
 	}
 
 	ou.IsPublic = public
-	_, err = x.Id(ou.Id).AllCols().Update(ou)
+	_, err = x.Id(ou.ID).AllCols().Update(ou)
 	return err
 }
 
@@ -316,7 +310,7 @@ func AddOrgUser(orgId, uid int64) error {
 
 	ou := &OrgUser{
 		Uid:   uid,
-		OrgId: orgId,
+		OrgID: orgId,
 	}
 
 	if _, err := sess.Insert(ou); err != nil {
@@ -367,7 +361,7 @@ func RemoveOrgUser(orgId, uid int64) error {
 		return err
 	}
 
-	if _, err := sess.Id(ou.Id).Delete(ou); err != nil {
+	if _, err := sess.Id(ou.ID).Delete(ou); err != nil {
 		sess.Rollback()
 		return err
 	} else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members - 1 WHERE id = ?", orgId); err != nil {
@@ -400,7 +394,7 @@ func RemoveOrgUser(orgId, uid int64) error {
 		return err
 	}
 	for _, t := range ts {
-		if err = removeTeamMember(sess, org.Id, t.Id, u.Id); err != nil {
+		if err = removeTeamMember(sess, org.Id, t.ID, u.Id); err != nil {
 			return err
 		}
 	}
@@ -419,13 +413,12 @@ const OWNER_TEAM = "Owners"
 
 // Team represents a organization team.
 type Team struct {
-	Id          int64
-	OrgId       int64 `xorm:"INDEX"`
+	ID          int64 `xorm:"pk autoincr"`
+	OrgID       int64 `xorm:"INDEX"`
 	LowerName   string
 	Name        string
 	Description string
 	Authorize   AccessMode
-	RepoIds     string        `xorm:"TEXT"`
 	Repos       []*Repository `xorm:"-"`
 	Members     []*User       `xorm:"-"`
 	NumRepos    int
@@ -439,23 +432,20 @@ func (t *Team) IsOwnerTeam() bool {
 
 // IsTeamMember returns true if given user is a member of team.
 func (t *Team) IsMember(uid int64) bool {
-	return IsTeamMember(t.OrgId, t.Id, uid)
+	return IsTeamMember(t.OrgID, t.ID, uid)
 }
 
-func (t *Team) getRepositories(e Engine) error {
-	idStrs := strings.Split(t.RepoIds, "|")
-	t.Repos = make([]*Repository, 0, len(idStrs))
-	for _, str := range idStrs {
-		if len(str) == 0 {
-			continue
-		}
-		id := com.StrTo(str[1:]).MustInt64()
-		if id == 0 {
-			continue
-		}
-		repo, err := getRepositoryById(e, id)
+func (t *Team) getRepositories(e Engine) (err error) {
+	teamRepos := make([]*TeamRepo, 0, t.NumRepos)
+	if err = x.Where("team_id=?", t.ID).Find(&teamRepos); err != nil {
+		return fmt.Errorf("get team-repos: %v", err)
+	}
+
+	t.Repos = make([]*Repository, 0, len(teamRepos))
+	for i := range teamRepos {
+		repo, err := getRepositoryById(e, teamRepos[i].RepoID)
 		if err != nil {
-			return err
+			return fmt.Errorf("getRepositoryById(%d): %v", teamRepos[i].RepoID, err)
 		}
 		t.Repos = append(t.Repos, repo)
 	}
@@ -468,7 +458,7 @@ func (t *Team) GetRepositories() error {
 }
 
 func (t *Team) getMembers(e Engine) (err error) {
-	t.Members, err = getTeamMembers(e, t.Id)
+	t.Members, err = getTeamMembers(e, t.ID)
 	return err
 }
 
@@ -479,96 +469,121 @@ func (t *Team) GetMembers() (err error) {
 
 // AddMember adds new member to team of organization.
 func (t *Team) AddMember(uid int64) error {
-	return AddTeamMember(t.OrgId, t.Id, uid)
+	return AddTeamMember(t.OrgID, t.ID, uid)
 }
 
 // RemoveMember removes member from team of organization.
 func (t *Team) RemoveMember(uid int64) error {
-	return RemoveTeamMember(t.OrgId, t.Id, uid)
+	return RemoveTeamMember(t.OrgID, t.ID, uid)
 }
 
-// AddRepository adds new repository to team of organization.
-func (t *Team) AddRepository(repo *Repository) (err error) {
-	idStr := "$" + com.ToStr(repo.Id) + "|"
-	if repo.OwnerId != t.OrgId {
-		return errors.New("Repository not belong to organization")
-	} else if strings.Contains(t.RepoIds, idStr) {
-		return nil
-	}
+func (t *Team) hasRepository(e Engine, repoID int64) bool {
+	return hasTeamRepo(e, t.OrgID, t.ID, repoID)
+}
 
-	if err = repo.GetOwner(); err != nil {
-		return err
-	} else if err = t.GetMembers(); err != nil {
-		return err
-	}
+// HasRepository returns true if given repository belong to team.
+func (t *Team) HasRepository(repoID int64) bool {
+	return HasTeamRepo(t.OrgID, t.ID, repoID)
+}
 
-	sess := x.NewSession()
-	defer sessionRelease(sess)
-	if err = sess.Begin(); err != nil {
+func (t *Team) addRepository(e Engine, repo *Repository) (err error) {
+	if err = addTeamRepo(e, t.OrgID, t.ID, repo.Id); err != nil {
 		return err
 	}
 
 	t.NumRepos++
-	t.RepoIds += idStr
-	if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
+	if _, err = e.Id(t.ID).AllCols().Update(t); err != nil {
 		return err
 	}
 
-	if err = repo.recalculateAccesses(sess); err != nil {
+	if err = repo.recalculateAccesses(e); err != nil {
 		return err
 	}
 
+	if err = t.getMembers(e); err != nil {
+		return fmt.Errorf("get team members: %v", err)
+	}
 	for _, u := range t.Members {
-		if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
+		if err = watchRepo(e, u.Id, repo.Id, true); err != nil {
 			return err
 		}
 	}
-	return sess.Commit()
-}
-
-func (t *Team) HasRepository(repo *Repository) bool {
-	idStr := "$" + com.ToStr(repo.Id) + "|"
-	return strings.Contains(t.RepoIds, idStr)
+	return nil
 }
 
-// RemoveRepository removes repository from team of organization.
-func (t *Team) RemoveRepository(repoId int64) error {
-	idStr := "$" + com.ToStr(repoId) + "|"
-	if !strings.Contains(t.RepoIds, idStr) {
+// AddRepository adds new repository to team of organization.
+func (t *Team) AddRepository(repo *Repository) (err error) {
+	if repo.OwnerId != t.OrgID {
+		return errors.New("Repository does not belong to organization")
+	} else if t.HasRepository(repo.Id) {
 		return nil
 	}
 
-	repo, err := GetRepositoryById(repoId)
-	if err != nil {
+	sess := x.NewSession()
+	defer sessionRelease(sess)
+	if err = sess.Begin(); err != nil {
 		return err
 	}
 
-	if err = repo.GetOwner(); err != nil {
-		return err
-	} else if err = t.GetMembers(); err != nil {
+	if err = t.addRepository(sess, repo); err != nil {
 		return err
 	}
 
-	sess := x.NewSession()
-	defer sessionRelease(sess)
-	if err = sess.Begin(); err != nil {
+	return sess.Commit()
+}
+
+func (t *Team) removeRepository(e Engine, repo *Repository) (err error) {
+	if err = removeTeamRepo(e, t.ID, repo.Id); err != nil {
 		return err
 	}
 
 	t.NumRepos--
-	t.RepoIds = strings.Replace(t.RepoIds, idStr, "", 1)
-	if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
+	if _, err = e.Id(t.ID).AllCols().Update(t); err != nil {
 		return err
 	}
 
-	if err = repo.recalculateAccesses(sess); err != nil {
+	if err = repo.recalculateAccesses(e); err != nil {
 		return err
 	}
 
+	if err = t.getMembers(e); err != nil {
+		return fmt.Errorf("get team members: %v", err)
+	}
 	for _, u := range t.Members {
-		if err = watchRepo(sess, u.Id, repo.Id, false); err != nil {
+		has, err := hasAccess(e, u, repo, ACCESS_MODE_READ)
+		if err != nil {
 			return err
+		} else if has {
+			continue
 		}
+
+		if err = watchRepo(e, u.Id, repo.Id, false); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// RemoveRepository removes repository from team of organization.
+func (t *Team) RemoveRepository(repoID int64) error {
+	if !t.HasRepository(repoID) {
+		return nil
+	}
+
+	repo, err := GetRepositoryById(repoID)
+	if err != nil {
+		return err
+	}
+
+	sess := x.NewSession()
+	defer sessionRelease(sess)
+	if err = sess.Begin(); err != nil {
+		return err
+	}
+
+	if err = t.removeRepository(sess, repo); err != nil {
+		return err
 	}
 
 	return sess.Commit()
@@ -581,7 +596,7 @@ func NewTeam(t *Team) error {
 		return ErrTeamNameIllegal
 	}
 
-	has, err := x.Id(t.OrgId).Get(new(User))
+	has, err := x.Id(t.OrgID).Get(new(User))
 	if err != nil {
 		return err
 	} else if !has {
@@ -589,7 +604,7 @@ func NewTeam(t *Team) error {
 	}
 
 	t.LowerName = strings.ToLower(t.Name)
-	has, err = x.Where("org_id=?", t.OrgId).And("lower_name=?", t.LowerName).Get(new(Team))
+	has, err = x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).Get(new(Team))
 	if err != nil {
 		return err
 	} else if has {
@@ -608,7 +623,7 @@ func NewTeam(t *Team) error {
 	}
 
 	// Update organization number of teams.
-	if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgId); err != nil {
+	if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgID); err != nil {
 		sess.Rollback()
 		return err
 	}
@@ -617,7 +632,7 @@ func NewTeam(t *Team) error {
 
 func getTeam(e Engine, orgId int64, name string) (*Team, error) {
 	t := &Team{
-		OrgId:     orgId,
+		OrgID:     orgId,
 		LowerName: strings.ToLower(name),
 	}
 	has, err := e.Get(t)
@@ -667,7 +682,7 @@ func UpdateTeam(t *Team, authChanged bool) (err error) {
 	}
 
 	t.LowerName = strings.ToLower(t.Name)
-	if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
+	if _, err = sess.Id(t.ID).AllCols().Update(t); err != nil {
 		return err
 	}
 
@@ -697,7 +712,7 @@ func DeleteTeam(t *Team) error {
 	}
 
 	// Get organization.
-	org, err := GetUserById(t.OrgId)
+	org, err := GetUserById(t.OrgID)
 	if err != nil {
 		return err
 	}
@@ -716,16 +731,16 @@ func DeleteTeam(t *Team) error {
 	}
 
 	// Delete team-user.
-	if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.Id).Delete(new(TeamUser)); err != nil {
+	if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.ID).Delete(new(TeamUser)); err != nil {
 		return err
 	}
 
 	// Delete team.
-	if _, err = sess.Id(t.Id).Delete(new(Team)); err != nil {
+	if _, err = sess.Id(t.ID).Delete(new(Team)); err != nil {
 		return err
 	}
 	// Update organization number of teams.
-	if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams - 1 WHERE id = ?", t.OrgId); err != nil {
+	if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil {
 		return err
 	}
 
@@ -741,20 +756,20 @@ func DeleteTeam(t *Team) error {
 
 // TeamUser represents an team-user relation.
 type TeamUser struct {
-	Id     int64
-	Uid    int64
-	OrgId  int64 `xorm:"INDEX"`
-	TeamId int64
+	ID     int64 `xorm:"pk autoincr"`
+	OrgID  int64 `xorm:"INDEX"`
+	TeamID int64 `xorm:"UNIQUE(s)"`
+	Uid    int64 `xorm:"UNIQUE(s)"`
 }
 
-func isTeamMember(e Engine, orgId, teamId, uid int64) bool {
-	has, _ := e.Where("uid=?", uid).And("org_id=?", orgId).And("team_id=?", teamId).Get(new(TeamUser))
+func isTeamMember(e Engine, orgID, teamID, uid int64) bool {
+	has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("uid=?", uid).Get(new(TeamUser))
 	return has
 }
 
 // IsTeamMember returns true if given user is a member of team.
-func IsTeamMember(orgId, teamId, uid int64) bool {
-	return isTeamMember(x, orgId, teamId, uid)
+func IsTeamMember(orgID, teamID, uid int64) bool {
+	return isTeamMember(x, orgID, teamID, uid)
 }
 
 func getTeamMembers(e Engine, teamID int64) ([]*User, error) {
@@ -777,7 +792,7 @@ func getUserTeams(e Engine, orgId, uid int64) ([]*Team, error) {
 	ts := make([]*Team, len(tus))
 	for i, tu := range tus {
 		t := new(Team)
-		has, err := e.Id(tu.TeamId).Get(t)
+		has, err := e.Id(tu.TeamID).Get(t)
 		if err != nil {
 			return nil, err
 		} else if !has {
@@ -822,13 +837,13 @@ func AddTeamMember(orgId, teamId, uid int64) error {
 
 	tu := &TeamUser{
 		Uid:    uid,
-		OrgId:  orgId,
-		TeamId: teamId,
+		OrgID:  orgId,
+		TeamID: teamId,
 	}
 
 	if _, err = sess.Insert(tu); err != nil {
 		return err
-	} else if _, err = sess.Id(t.Id).Update(t); err != nil {
+	} else if _, err = sess.Id(t.ID).Update(t); err != nil {
 		return err
 	}
 
@@ -848,7 +863,7 @@ func AddTeamMember(orgId, teamId, uid int64) error {
 	if t.IsOwnerTeam() {
 		ou.IsOwner = true
 	}
-	if _, err = sess.Id(ou.Id).AllCols().Update(ou); err != nil {
+	if _, err = sess.Id(ou.ID).AllCols().Update(ou); err != nil {
 		return err
 	}
 
@@ -885,13 +900,13 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error {
 
 	tu := &TeamUser{
 		Uid:    uid,
-		OrgId:  orgId,
-		TeamId: teamId,
+		OrgID:  orgId,
+		TeamID: teamId,
 	}
 
 	if _, err := e.Delete(tu); err != nil {
 		return err
-	} else if _, err = e.Id(t.Id).AllCols().Update(t); err != nil {
+	} else if _, err = e.Id(t.ID).AllCols().Update(t); err != nil {
 		return err
 	}
 
@@ -912,7 +927,7 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error {
 	if t.IsOwnerTeam() {
 		ou.IsOwner = false
 	}
-	if _, err = e.Id(ou.Id).AllCols().Update(ou); err != nil {
+	if _, err = e.Id(ou.ID).AllCols().Update(ou); err != nil {
 		return err
 	}
 	return nil
@@ -921,13 +936,64 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error {
 // RemoveTeamMember removes member from given team of given organization.
 func RemoveTeamMember(orgId, teamId, uid int64) error {
 	sess := x.NewSession()
-	defer sess.Close()
+	defer sessionRelease(sess)
 	if err := sess.Begin(); err != nil {
 		return err
 	}
 	if err := removeTeamMember(sess, orgId, teamId, uid); err != nil {
-		sess.Rollback()
 		return err
 	}
 	return sess.Commit()
 }
+
+// ___________                  __________
+// \__    ___/___ _____    _____\______   \ ____ ______   ____
+//   |    |_/ __ \\__  \  /     \|       _// __ \\____ \ /  _ \
+//   |    |\  ___/ / __ \|  Y Y  \    |   \  ___/|  |_> >  <_> )
+//   |____| \___  >____  /__|_|  /____|_  /\___  >   __/ \____/
+//              \/     \/      \/       \/     \/|__|
+
+// TeamRepo represents an team-repository relation.
+type TeamRepo struct {
+	ID     int64 `xorm:"pk autoincr"`
+	OrgID  int64 `xorm:"INDEX"`
+	TeamID int64 `xorm:"UNIQUE(s)"`
+	RepoID int64 `xorm:"UNIQUE(s)"`
+}
+
+func hasTeamRepo(e Engine, orgID, teamID, repoID int64) bool {
+	has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("repo_id=?", repoID).Get(new(TeamRepo))
+	return has
+}
+
+// HasTeamRepo returns true if given repository belongs to team.
+func HasTeamRepo(orgID, teamID, repoID int64) bool {
+	return hasTeamRepo(x, orgID, teamID, repoID)
+}
+
+func addTeamRepo(e Engine, orgID, teamID, repoID int64) error {
+	_, err := e.InsertOne(&TeamRepo{
+		OrgID:  orgID,
+		TeamID: teamID,
+		RepoID: repoID,
+	})
+	return err
+}
+
+// AddTeamRepo adds new repository relation to team.
+func AddTeamRepo(orgID, teamID, repoID int64) error {
+	return addTeamRepo(x, orgID, teamID, repoID)
+}
+
+func removeTeamRepo(e Engine, teamID, repoID int64) error {
+	_, err := e.Delete(&TeamRepo{
+		TeamID: teamID,
+		RepoID: repoID,
+	})
+	return err
+}
+
+// RemoveTeamRepo deletes repository relation to team.
+func RemoveTeamRepo(teamID, repoID int64) error {
+	return removeTeamRepo(x, teamID, repoID)
+}

+ 57 - 75
models/repo.go

@@ -514,7 +514,7 @@ func initRepository(e Engine, f string, u *User, repo *Repository, initReadme bo
 }
 
 // CreateRepository creates a repository for given user or organization.
-func CreateRepository(u *User, name, desc, lang, license string, private, mirror, initReadme bool) (*Repository, error) {
+func CreateRepository(u *User, name, desc, lang, license string, isPrivate, isMirror, initReadme bool) (*Repository, error) {
 	if !IsLegalName(name) {
 		return nil, ErrRepoNameIllegal
 	}
@@ -532,7 +532,7 @@ func CreateRepository(u *User, name, desc, lang, license string, private, mirror
 		Name:        name,
 		LowerName:   strings.ToLower(name),
 		Description: desc,
-		IsPrivate:   private,
+		IsPrivate:   isPrivate,
 	}
 
 	sess := x.NewSession()
@@ -558,34 +558,22 @@ func CreateRepository(u *User, name, desc, lang, license string, private, mirror
 		// Update owner team info and count.
 		t, err := u.getOwnerTeam(sess)
 		if err != nil {
-			return nil, fmt.Errorf("get owner team: %v", err)
-		} else if err = t.getMembers(sess); err != nil {
-			return nil, fmt.Errorf("get team members: %v", err)
-		}
-
-		for _, u := range t.Members {
-			if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
-				return nil, fmt.Errorf("watch repository: %v", err)
-			}
-		}
-
-		t.RepoIds += "$" + com.ToStr(repo.Id) + "|"
-		t.NumRepos++
-		if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
-			return nil, err
+			return nil, fmt.Errorf("getOwnerTeam: %v", err)
+		} else if err = t.addRepository(sess, repo); err != nil {
+			return nil, fmt.Errorf("addRepository: %v", err)
 		}
 	} else {
 		if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
-			return nil, fmt.Errorf("watch repository 2: %v", err)
+			return nil, fmt.Errorf("watchRepo: %v", err)
 		}
 	}
 
 	if err = newRepoAction(sess, u, repo); err != nil {
-		return nil, fmt.Errorf("new repository action: %v", err)
+		return nil, fmt.Errorf("newRepoAction: %v", err)
 	}
 
 	// No need for init mirror.
-	if !mirror {
+	if !isMirror {
 		repoPath := RepoPath(u.Name, repo.Name)
 		if err = initRepository(sess, repoPath, u, repo, initReadme, lang, license); err != nil {
 			if err2 := os.RemoveAll(repoPath); err2 != nil {
@@ -640,14 +628,14 @@ func RepoPath(userName, repoName string) string {
 }
 
 // TransferOwnership transfers all corresponding setting from old user to new one.
-func TransferOwnership(u *User, newOwner string, repo *Repository) error {
-	newUser, err := GetUserByName(newOwner)
+func TransferOwnership(u *User, newOwnerName string, repo *Repository) error {
+	newOwner, err := GetUserByName(newOwnerName)
 	if err != nil {
-		return fmt.Errorf("fail to get new owner(%s): %v", newOwner, err)
+		return fmt.Errorf("get new owner(%s): %v", newOwnerName, err)
 	}
 
 	// Check if new owner has repository with same name.
-	has, err := IsRepositoryExist(newUser, repo.Name)
+	has, err := IsRepositoryExist(newOwner, repo.Name)
 	if err != nil {
 		return err
 	} else if has {
@@ -663,8 +651,8 @@ func TransferOwnership(u *User, newOwner string, repo *Repository) error {
 	owner := repo.Owner
 
 	// Update repository.
-	repo.OwnerId = newUser.Id
-	repo.Owner = newUser
+	repo.OwnerId = newOwner.Id
+	repo.Owner = newOwner
 	if _, err := sess.Id(repo.Id).Update(repo); err != nil {
 		return err
 	}
@@ -675,28 +663,38 @@ func TransferOwnership(u *User, newOwner string, repo *Repository) error {
 		return err
 	}
 	for _, c := range collaborators {
-		if c.Id == newUser.Id || newUser.IsOrgMember(c.Id) {
+		if c.Id == newOwner.Id || newOwner.IsOrgMember(c.Id) {
 			if _, err = sess.Delete(&Collaboration{RepoID: repo.Id, UserID: c.Id}); err != nil {
 				return err
 			}
 		}
 	}
 
+	if newOwner.IsOrganization() {
+		// Update owner team info and count.
+		t, err := newOwner.GetOwnerTeam()
+		if err != nil {
+			return err
+		} else if err = t.addRepository(sess, repo); err != nil {
+			return err
+		}
+	}
+
 	// Update user repository number.
-	if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?", newUser.Id); err != nil {
+	if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?", newOwner.Id); err != nil {
 		return err
 	} else if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", owner.Id); err != nil {
 		return err
 	} else if err = repo.recalculateAccesses(sess); err != nil {
 		return err
-	} else if err = watchRepo(sess, newUser.Id, repo.Id, true); err != nil {
+	} else if err = watchRepo(sess, newOwner.Id, repo.Id, true); err != nil {
 		return err
-	} else if err = transferRepoAction(sess, u, newUser, repo); err != nil {
+	} else if err = transferRepoAction(sess, u, owner, newOwner, repo); err != nil {
 		return err
 	}
 
 	// Change repository directory name.
-	if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newUser.Name, repo.Name)); err != nil {
+	if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil {
 		return err
 	}
 
@@ -734,8 +732,8 @@ func UpdateRepository(repo *Repository) error {
 }
 
 // DeleteRepository deletes a repository for a user or organization.
-func DeleteRepository(uid, repoId int64, userName string) error {
-	repo := &Repository{Id: repoId, OwnerId: uid}
+func DeleteRepository(uid, repoID int64, userName string) error {
+	repo := &Repository{Id: repoID, OwnerId: uid}
 	has, err := x.Get(repo)
 	if err != nil {
 		return err
@@ -761,70 +759,66 @@ func DeleteRepository(uid, repoId int64, userName string) error {
 	}
 
 	if org.IsOrganization() {
-		idStr := "$" + com.ToStr(repoId) + "|"
 		for _, t := range org.Teams {
-			if !strings.Contains(t.RepoIds, idStr) {
+			if !t.hasRepository(sess, repoID) {
 				continue
-			}
-			t.NumRepos--
-			t.RepoIds = strings.Replace(t.RepoIds, idStr, "", 1)
-			if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
+			} else if err = t.removeRepository(sess, repo); err != nil {
 				return err
 			}
 		}
 	}
 
-	if _, err = sess.Delete(&Repository{Id: repoId}); err != nil {
+	if _, err = sess.Delete(&Repository{Id: repoID}); err != nil {
 		return err
 	} else if _, err := sess.Delete(&Access{RepoID: repo.Id}); err != nil {
 		return err
 	} else if _, err := sess.Delete(&Action{RepoId: repo.Id}); err != nil {
 		return err
-	} else if _, err = sess.Delete(&Watch{RepoId: repoId}); err != nil {
+	} else if _, err = sess.Delete(&Watch{RepoId: repoID}); err != nil {
 		return err
-	} else if _, err = sess.Delete(&Mirror{RepoId: repoId}); err != nil {
+	} else if _, err = sess.Delete(&Mirror{RepoId: repoID}); err != nil {
 		return err
-	} else if _, err = sess.Delete(&IssueUser{RepoId: repoId}); err != nil {
+	} else if _, err = sess.Delete(&IssueUser{RepoId: repoID}); err != nil {
 		return err
-	} else if _, err = sess.Delete(&Milestone{RepoId: repoId}); err != nil {
+	} else if _, err = sess.Delete(&Milestone{RepoId: repoID}); err != nil {
 		return err
-	} else if _, err = sess.Delete(&Release{RepoId: repoId}); err != nil {
+	} else if _, err = sess.Delete(&Release{RepoId: repoID}); err != nil {
 		return err
-	} else if _, err = sess.Delete(&Collaboration{RepoID: repoId}); err != nil {
+	} else if _, err = sess.Delete(&Collaboration{RepoID: repoID}); err != nil {
 		return err
 	}
 
 	// Delete comments.
-	if err = x.Iterate(&Issue{RepoId: repoId}, func(idx int, bean interface{}) error {
-		issue := bean.(*Issue)
-		if _, err = sess.Delete(&Comment{IssueId: issue.Id}); err != nil {
+	issues := make([]*Issue, 0, 25)
+	if err = sess.Where("repo_id=?", repoID).Find(&issues); err != nil {
+		return err
+	}
+	for i := range issues {
+		if _, err = sess.Delete(&Comment{IssueId: issues[i].Id}); err != nil {
 			return err
 		}
-		return nil
-	}); err != nil {
-		return err
 	}
 
-	if _, err = sess.Delete(&Issue{RepoId: repoId}); err != nil {
+	if _, err = sess.Delete(&Issue{RepoId: repoID}); err != nil {
 		return err
 	}
 
 	if repo.IsFork {
-		if _, err = sess.Exec("UPDATE `repository` SET num_forks = num_forks - 1 WHERE id = ?", repo.ForkId); err != nil {
+		if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkId); err != nil {
 			return err
 		}
 	}
 
-	if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", uid); err != nil {
+	if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", uid); err != nil {
 		return err
 	}
 
 	// Remove repository files.
 	if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil {
-		desc := fmt.Sprintf("Fail to delete repository files(%s/%s): %v", userName, repo.Name, err)
+		desc := fmt.Sprintf("delete repository files(%s/%s): %v", userName, repo.Name, err)
 		log.Warn(desc)
 		if err = CreateRepositoryNotice(desc); err != nil {
-			log.Error(4, "Fail to add notice: %v", err)
+			log.Error(4, "add notice: %v", err)
 		}
 	}
 
@@ -1328,33 +1322,21 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (*Repositor
 		// Update owner team info and count.
 		t, err := u.getOwnerTeam(sess)
 		if err != nil {
-			return nil, fmt.Errorf("get owner team: %v", err)
-		} else if err = t.getMembers(sess); err != nil {
-			return nil, fmt.Errorf("get team members: %v", err)
-		}
-
-		for _, u := range t.Members {
-			if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
-				return nil, fmt.Errorf("watch repository: %v", err)
-			}
-		}
-
-		t.RepoIds += "$" + com.ToStr(repo.Id) + "|"
-		t.NumRepos++
-		if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil {
-			return nil, err
+			return nil, fmt.Errorf("getOwnerTeam: %v", err)
+		} else if err = t.addRepository(sess, repo); err != nil {
+			return nil, fmt.Errorf("addRepository: %v", err)
 		}
 	} else {
 		if err = watchRepo(sess, u.Id, repo.Id, true); err != nil {
-			return nil, fmt.Errorf("watch repository 2: %v", err)
+			return nil, fmt.Errorf("watchRepo: %v", err)
 		}
 	}
 
 	if err = newRepoAction(sess, u, repo); err != nil {
-		return nil, fmt.Errorf("new repository action: %v", err)
+		return nil, fmt.Errorf("newRepoAction: %v", err)
 	}
 
-	if _, err = sess.Exec("UPDATE `repository` SET num_forks = num_forks + 1 WHERE id = ?", oldRepo.Id); err != nil {
+	if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", oldRepo.Id); err != nil {
 		return nil, err
 	}
 

+ 2 - 2
models/user.go

@@ -231,7 +231,7 @@ func (u *User) GetOrganizations() error {
 
 	u.Orgs = make([]*User, len(ous))
 	for i, ou := range ous {
-		u.Orgs[i], err = GetUserById(ou.OrgId)
+		u.Orgs[i], err = GetUserById(ou.OrgID)
 		if err != nil {
 			return err
 		}
@@ -860,7 +860,7 @@ func UpdateMentions(userNames []string, issueId int64) error {
 		}
 
 		for _, orgUser := range orgUsers {
-			tempIds = append(tempIds, orgUser.Id)
+			tempIds = append(tempIds, orgUser.ID)
 		}
 
 		ids = append(ids, tempIds...)

+ 1 - 1
routers/org/teams.go

@@ -181,7 +181,7 @@ func NewTeamPost(ctx *middleware.Context, form auth.CreateTeamForm) {
 	org := ctx.Org.Organization
 
 	t := &models.Team{
-		OrgId:       org.Id,
+		OrgID:       org.Id,
 		Name:        form.TeamName,
 		Description: form.Description,
 		Authorize:   auth,

+ 0 - 1
routers/repo/setting.go

@@ -8,7 +8,6 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"path"
 	"strings"
 	"time"
 

+ 1 - 1
templates/.VERSION

@@ -1 +1 @@
-0.5.14.0222 Beta
+0.5.15.0223 Beta