aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
Diffstat (limited to 'models')
-rw-r--r--models/error.go43
-rw-r--r--models/git_diff.go61
-rw-r--r--models/org.go106
-rw-r--r--models/pull.go17
-rw-r--r--models/repo.go45
-rw-r--r--models/repo_branch.go57
-rw-r--r--models/ssh_key.go8
-rw-r--r--models/user.go10
-rw-r--r--models/webhook.go2
9 files changed, 290 insertions, 59 deletions
diff --git a/models/error.go b/models/error.go
index 83a24e7f..cd7fa35d 100644
--- a/models/error.go
+++ b/models/error.go
@@ -392,6 +392,26 @@ func (err ErrReleaseNotExist) Error() string {
return fmt.Sprintf("Release tag does not exist [id: %d, tag_name: %s]", err.ID, err.TagName)
}
+// __________ .__
+// \______ \____________ ____ ____ | |__
+// | | _/\_ __ \__ \ / \_/ ___\| | \
+// | | \ | | \// __ \| | \ \___| Y \
+// |______ / |__| (____ /___| /\___ >___| /
+// \/ \/ \/ \/ \/
+
+type ErrBranchNotExist struct {
+ Name string
+}
+
+func IsErrBranchNotExist(err error) bool {
+ _, ok := err.(ErrBranchNotExist)
+ return ok
+}
+
+func (err ErrBranchNotExist) Error() string {
+ return fmt.Sprintf("Branch does not exist [name: %s]", err.Name)
+}
+
// __ __ ___. .__ __
// / \ / \ ____\_ |__ | |__ ____ ____ | | __
// \ \/\/ // __ \| __ \| | \ / _ \ / _ \| |/ /
@@ -559,5 +579,26 @@ func IsErrAuthenticationNotExist(err error) bool {
}
func (err ErrAuthenticationNotExist) Error() string {
- return fmt.Sprintf("Authentication does not exist [id: %d]", err.ID)
+ return fmt.Sprintf("authentication does not exist [id: %d]", err.ID)
+}
+
+// ___________
+// \__ ___/___ _____ _____
+// | |_/ __ \\__ \ / \
+// | |\ ___/ / __ \| Y Y \
+// |____| \___ >____ /__|_| /
+// \/ \/ \/
+
+type ErrTeamAlreadyExist struct {
+ OrgID int64
+ Name string
+}
+
+func IsErrTeamAlreadyExist(err error) bool {
+ _, ok := err.(ErrTeamAlreadyExist)
+ return ok
+}
+
+func (err ErrTeamAlreadyExist) Error() string {
+ return fmt.Sprintf("team already exists [org_id: %d, name: %s]", err.OrgID, err.Name)
}
diff --git a/models/git_diff.go b/models/git_diff.go
index 1913ec46..e8bfe610 100644
--- a/models/git_diff.go
+++ b/models/git_diff.go
@@ -51,7 +51,6 @@ type DiffLine struct {
RightIdx int
Type DiffLineType
Content string
- ParsedContent template.HTML
}
func (d *DiffLine) GetType() int {
@@ -112,42 +111,42 @@ func (diffSection *DiffSection) GetLine(lineType DiffLineType, idx int) *DiffLin
return nil
}
-// computes diff of each diff line and set the HTML on diffLine.ParsedContent
-func (diffSection *DiffSection) ComputeLinesDiff() {
- for _, diffLine := range diffSection.Lines {
- var compareDiffLine *DiffLine
- var diff1, diff2 string
+// computes inline diff for the given line
+func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) template.HTML {
+ var compareDiffLine *DiffLine
+ var diff1, diff2 string
- diffLine.ParsedContent = template.HTML(html.EscapeString(diffLine.Content[1:]))
+ getDefaultReturn := func() template.HTML {
+ return template.HTML(html.EscapeString(diffLine.Content[1:]))
+ }
- // just compute diff for adds and removes
- if diffLine.Type != DIFF_LINE_ADD && diffLine.Type != DIFF_LINE_DEL {
- continue
- }
+ // just compute diff for adds and removes
+ if diffLine.Type != DIFF_LINE_ADD && diffLine.Type != DIFF_LINE_DEL {
+ return getDefaultReturn()
+ }
- // try to find equivalent diff line. ignore, otherwise
- if diffLine.Type == DIFF_LINE_ADD {
- compareDiffLine = diffSection.GetLine(DIFF_LINE_DEL, diffLine.RightIdx)
- if compareDiffLine == nil {
- continue
- }
- diff1 = compareDiffLine.Content
- diff2 = diffLine.Content
- } else {
- compareDiffLine = diffSection.GetLine(DIFF_LINE_ADD, diffLine.LeftIdx)
- if compareDiffLine == nil {
- continue
- }
- diff1 = diffLine.Content
- diff2 = compareDiffLine.Content
+ // try to find equivalent diff line. ignore, otherwise
+ if diffLine.Type == DIFF_LINE_ADD {
+ compareDiffLine = diffSection.GetLine(DIFF_LINE_DEL, diffLine.RightIdx)
+ if compareDiffLine == nil {
+ return getDefaultReturn()
+ }
+ diff1 = compareDiffLine.Content
+ diff2 = diffLine.Content
+ } else {
+ compareDiffLine = diffSection.GetLine(DIFF_LINE_ADD, diffLine.LeftIdx)
+ if compareDiffLine == nil {
+ return getDefaultReturn()
}
+ diff1 = diffLine.Content
+ diff2 = compareDiffLine.Content
+ }
- dmp := diffmatchpatch.New()
- diffRecord := dmp.DiffMain(diff1[1:], diff2[1:], true)
- diffRecord = dmp.DiffCleanupSemantic(diffRecord)
+ dmp := diffmatchpatch.New()
+ diffRecord := dmp.DiffMain(diff1[1:], diff2[1:], true)
+ diffRecord = dmp.DiffCleanupSemantic(diffRecord)
- diffLine.ParsedContent = diffToHTML(diffRecord, diffLine.Type)
- }
+ return diffToHTML(diffRecord, diffLine.Type)
}
type DiffFile struct {
diff --git a/models/org.go b/models/org.go
index fa26b59e..020284d8 100644
--- a/models/org.go
+++ b/models/org.go
@@ -10,14 +10,13 @@ import (
"os"
"strings"
+ "github.com/Unknwon/com"
"github.com/go-xorm/xorm"
)
var (
- ErrOrgNotExist = errors.New("Organization does not exist")
- ErrTeamAlreadyExist = errors.New("Team already exist")
- ErrTeamNotExist = errors.New("Team does not exist")
- ErrTeamNameIllegal = errors.New("Team name contains illegal characters")
+ ErrOrgNotExist = errors.New("Organization does not exist")
+ ErrTeamNotExist = errors.New("Team does not exist")
)
// IsOwnedBy returns true if given user is in the owner team.
@@ -255,6 +254,26 @@ func IsPublicMembership(orgId, uid int64) bool {
return has
}
+func getPublicOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) {
+ orgs := make([]*User, 0, 10)
+ return orgs, sess.Where("`org_user`.uid=?", userID).And("`org_user`.is_public=?", true).
+ Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id").Find(&orgs)
+}
+
+// GetPublicOrgsByUserID returns a list of organizations that the given user ID
+// has joined publicly.
+func GetPublicOrgsByUserID(userID int64) ([]*User, error) {
+ sess := x.NewSession()
+ return getPublicOrgsByUserID(sess, userID)
+}
+
+// GetPublicOrgsByUserID returns a list of organizations that the given user ID
+// has joined publicly, ordered descending by the given condition.
+func GetPublicOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
+ sess := x.NewSession()
+ return getPublicOrgsByUserID(sess.Desc(desc), userID)
+}
+
func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) {
orgs := make([]*User, 0, 10)
return orgs, sess.Where("`org_user`.uid=?", userID).And("`org_user`.is_owner=?", true).
@@ -268,7 +287,7 @@ func GetOwnedOrgsByUserID(userID int64) ([]*User, error) {
}
// GetOwnedOrganizationsByUserIDDesc returns a list of organizations are owned by
-// given user ID and descring order by given condition.
+// given user ID, ordered descending by the given condition.
func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
sess := x.NewSession()
return getOwnedOrgsByUserID(sess.Desc(desc), userID)
@@ -598,9 +617,9 @@ func (t *Team) RemoveRepository(repoID int64) error {
// NewTeam creates a record of new team.
// It's caller's responsibility to assign organization ID.
-func NewTeam(t *Team) (err error) {
- if err = IsUsableName(t.Name); err != nil {
- return err
+func NewTeam(t *Team) error {
+ if len(t.Name) == 0 {
+ return errors.New("empty team name")
}
has, err := x.Id(t.OrgID).Get(new(User))
@@ -615,7 +634,7 @@ func NewTeam(t *Team) (err error) {
if err != nil {
return err
} else if has {
- return ErrTeamAlreadyExist
+ return ErrTeamAlreadyExist{t.OrgID, t.LowerName}
}
sess := x.NewSession()
@@ -674,8 +693,8 @@ func GetTeamById(teamId int64) (*Team, error) {
// UpdateTeam updates information of team.
func UpdateTeam(t *Team, authChanged bool) (err error) {
- if err = IsUsableName(t.Name); err != nil {
- return err
+ if len(t.Name) == 0 {
+ return errors.New("empty team name")
}
if len(t.Description) > 255 {
@@ -689,6 +708,13 @@ func UpdateTeam(t *Team, authChanged bool) (err error) {
}
t.LowerName = strings.ToLower(t.Name)
+ has, err := x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).And("id!=?", t.ID).Get(new(Team))
+ if err != nil {
+ return err
+ } else if has {
+ return ErrTeamAlreadyExist{t.OrgID, t.LowerName}
+ }
+
if _, err = sess.Id(t.ID).AllCols().Update(t); err != nil {
return fmt.Errorf("update: %v", err)
}
@@ -1023,3 +1049,61 @@ func removeOrgRepo(e Engine, orgID, repoID int64) error {
func RemoveOrgRepo(orgID, repoID int64) error {
return removeOrgRepo(x, orgID, repoID)
}
+
+// GetUserRepositories gets all repositories of an organization,
+// that the user with the given userID has access to.
+func (org *User) GetUserRepositories(userID int64) (err error) {
+ teams := make([]*Team, 0, 10)
+ if err = x.Cols("`team`.id").
+ Where("`team_user`.org_id=?", org.Id).
+ And("`team_user`.uid=?", userID).
+ Join("INNER", "`team_user`", "`team_user`.team_id=`team`.id").
+ Find(&teams); err != nil {
+ return fmt.Errorf("GetUserRepositories: get teams: %v", err)
+ }
+
+ teamIDs := make([]string, len(teams))
+ for i := range teams {
+ teamIDs[i] = com.ToStr(teams[i].ID)
+ }
+ if len(teamIDs) == 0 {
+ // user has no team but "IN ()" is invalid SQL
+ teamIDs = append(teamIDs, "-1") // there is no repo with id=-1
+ }
+
+ // Due to a bug in xorm using IN() together with OR() is impossible.
+ // As a workaround, we have to build the IN statement on our own, until this is fixed.
+ // https://github.com/go-xorm/xorm/issues/342
+
+ if err = x.Cols("`repository`.*").
+ Join("INNER", "`team_repo`", "`team_repo`.repo_id=`repository`.id").
+ Where("`repository`.owner_id=?", org.Id).
+ And("`repository`.is_private=?", false).
+ Or("`team_repo`.team_id=(?)", strings.Join(teamIDs, ",")).
+ GroupBy("`repository`.id").
+ Find(&org.Repos); err != nil {
+ return fmt.Errorf("GetUserRepositories: get repositories: %v", err)
+ }
+
+ // FIXME: should I change this value inside method,
+ // or only in location of caller where it's really needed?
+ org.NumRepos = len(org.Repos)
+ return nil
+}
+
+// GetTeams returns all teams that belong to organization,
+// and that the user has joined.
+func (org *User) GetUserTeams(userID int64) error {
+ if err := x.Cols("`team`.*").
+ Where("`team_user`.org_id=?", org.Id).
+ And("`team_user`.uid=?", userID).
+ Join("INNER", "`team_user`", "`team_user`.team_id=`team`.id").
+ Find(&org.Teams); err != nil {
+ return fmt.Errorf("GetUserTeams: %v", err)
+ }
+
+ // FIXME: should I change this value inside method,
+ // or only in location of caller where it's really needed?
+ org.NumTeams = len(org.Teams)
+ return nil
+}
diff --git a/models/pull.go b/models/pull.go
index 8497285e..330319f9 100644
--- a/models/pull.go
+++ b/models/pull.go
@@ -256,6 +256,7 @@ var patchConflicts = []string{
"patch does not apply",
"already exists in working directory",
"unrecognized input",
+ "error:",
}
// testPatch checks if patch can be merged to base repository without conflit.
@@ -279,7 +280,7 @@ func (pr *PullRequest) testPatch() (err error) {
return nil
}
- log.Trace("PullRequest[%d].testPatch(patchPath): %s", pr.ID, patchPath)
+ log.Trace("PullRequest[%d].testPatch (patchPath): %s", pr.ID, patchPath)
if err := pr.BaseRepo.UpdateLocalCopy(); err != nil {
return fmt.Errorf("UpdateLocalCopy: %v", err)
@@ -287,7 +288,7 @@ func (pr *PullRequest) testPatch() (err error) {
// Checkout base branch.
_, stderr, err := process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
- fmt.Sprintf("PullRequest.Merge(git checkout): %v", pr.BaseRepo.ID),
+ fmt.Sprintf("PullRequest.Merge (git checkout): %v", pr.BaseRepo.ID),
"git", "checkout", pr.BaseBranch)
if err != nil {
return fmt.Errorf("git checkout: %s", stderr)
@@ -295,12 +296,12 @@ func (pr *PullRequest) testPatch() (err error) {
pr.Status = PULL_REQUEST_STATUS_CHECKING
_, stderr, err = process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
- fmt.Sprintf("testPatch(git apply --check): %d", pr.BaseRepo.ID),
+ fmt.Sprintf("testPatch (git apply --check): %d", pr.BaseRepo.ID),
"git", "apply", "--check", patchPath)
if err != nil {
for i := range patchConflicts {
if strings.Contains(stderr, patchConflicts[i]) {
- log.Trace("PullRequest[%d].testPatch(apply): has conflit", pr.ID)
+ log.Trace("PullRequest[%d].testPatch (apply): has conflit", pr.ID)
fmt.Println(stderr)
pr.Status = PULL_REQUEST_STATUS_CONFLICT
return nil
@@ -525,6 +526,14 @@ func AddTestPullRequestTask(repoID int64, branch string) {
}
}
+func ChangeUsernameInPullRequests(oldUserName, newUserName string) error {
+ pr := PullRequest{
+ HeadUserName: strings.ToLower(newUserName),
+ }
+ _, err := x.Cols("head_user_name").Where("head_user_name = ?", strings.ToLower(oldUserName)).Update(pr)
+ return err
+}
+
// checkAndUpdateStatus checks if pull request is possible to levaing checking status,
// and set to be either conflict or mergeable.
func (pr *PullRequest) checkAndUpdateStatus() {
diff --git a/models/repo.go b/models/repo.go
index e53d8065..868498bc 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -1457,9 +1457,8 @@ func DeleteRepositoryArchives() error {
})
}
-// DeleteMissingRepositories deletes all repository records that lost Git files.
-func DeleteMissingRepositories() error {
- repos := make([]*Repository, 0, 5)
+func gatherMissingRepoRecords() ([]*Repository, error) {
+ repos := make([]*Repository, 0, 10)
if err := x.Where("id > 0").Iterate(new(Repository),
func(idx int, bean interface{}) error {
repo := bean.(*Repository)
@@ -1468,10 +1467,18 @@ func DeleteMissingRepositories() error {
}
return nil
}); err != nil {
- if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteMissingRepositories: %v", err)); err2 != nil {
- log.Error(4, "CreateRepositoryNotice: %v", err2)
+ if err2 := CreateRepositoryNotice(fmt.Sprintf("gatherMissingRepoRecords: %v", err)); err2 != nil {
+ return nil, fmt.Errorf("CreateRepositoryNotice: %v", err)
}
- return nil
+ }
+ return repos, nil
+}
+
+// DeleteMissingRepositories deletes all repository records that lost Git files.
+func DeleteMissingRepositories() error {
+ repos, err := gatherMissingRepoRecords()
+ if err != nil {
+ return fmt.Errorf("gatherMissingRepoRecords: %v", err)
}
if len(repos) == 0 {
@@ -1482,7 +1489,29 @@ func DeleteMissingRepositories() error {
log.Trace("Deleting %d/%d...", repo.OwnerID, repo.ID)
if err := DeleteRepository(repo.OwnerID, repo.ID); err != nil {
if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepository [%d]: %v", repo.ID, err)); err2 != nil {
- log.Error(4, "CreateRepositoryNotice: %v", err2)
+ return fmt.Errorf("CreateRepositoryNotice: %v", err)
+ }
+ }
+ }
+ return nil
+}
+
+// ReinitMissingRepositories reinitializes all repository records that lost Git files.
+func ReinitMissingRepositories() error {
+ repos, err := gatherMissingRepoRecords()
+ if err != nil {
+ return fmt.Errorf("gatherMissingRepoRecords: %v", err)
+ }
+
+ if len(repos) == 0 {
+ return nil
+ }
+
+ for _, repo := range repos {
+ log.Trace("Initializing %d/%d...", repo.OwnerID, repo.ID)
+ if err := git.InitRepository(repo.RepoPath(), true); err != nil {
+ if err2 := CreateRepositoryNotice(fmt.Sprintf("InitRepository [%d]: %v", repo.ID, err)); err2 != nil {
+ return fmt.Errorf("CreateRepositoryNotice: %v", err)
}
}
}
@@ -1602,7 +1631,7 @@ func GitFsck() {
repo := bean.(*Repository)
repoPath := repo.RepoPath()
if err := git.Fsck(repoPath, setting.Cron.RepoHealthCheck.Timeout, setting.Cron.RepoHealthCheck.Args...); err != nil {
- desc := fmt.Sprintf("Fail to health check repository(%s)", repoPath)
+ desc := fmt.Sprintf("Fail to health check repository (%s): %v", repoPath, err)
log.Warn(desc)
if err = CreateRepositoryNotice(desc); err != nil {
log.Error(4, "CreateRepositoryNotice: %v", err)
diff --git a/models/repo_branch.go b/models/repo_branch.go
new file mode 100644
index 00000000..9cf2e9c4
--- /dev/null
+++ b/models/repo_branch.go
@@ -0,0 +1,57 @@
+// Copyright 2016 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package models
+
+import (
+ "github.com/gogits/git-module"
+)
+
+type Branch struct {
+ Path string
+ Name string
+}
+
+func GetBranchesByPath(path string) ([]*Branch, error) {
+ gitRepo, err := git.OpenRepository(path)
+ if err != nil {
+ return nil, err
+ }
+
+ brs, err := gitRepo.GetBranches()
+ if err != nil {
+ return nil, err
+ }
+
+ branches := make([]*Branch, len(brs))
+ for i := range brs {
+ branches[i] = &Branch{
+ Path: path,
+ Name: brs[i],
+ }
+ }
+ return branches, nil
+}
+
+func (repo *Repository) GetBranch(br string) (*Branch, error) {
+ if !git.IsBranchExist(repo.RepoPath(), br) {
+ return nil, &ErrBranchNotExist{br}
+ }
+ return &Branch{
+ Path: repo.RepoPath(),
+ Name: br,
+ }, nil
+}
+
+func (repo *Repository) GetBranches() ([]*Branch, error) {
+ return GetBranchesByPath(repo.RepoPath())
+}
+
+func (br *Branch) GetCommit() (*git.Commit, error) {
+ gitRepo, err := git.OpenRepository(br.Path)
+ if err != nil {
+ return nil, err
+ }
+ return gitRepo.GetBranchCommit(br.Name)
+}
diff --git a/models/ssh_key.go b/models/ssh_key.go
index a7b1680f..325a40a4 100644
--- a/models/ssh_key.go
+++ b/models/ssh_key.go
@@ -165,6 +165,9 @@ func CheckPublicKeyString(content string) (_ string, err error) {
return "", errors.New("only a single line with a single key please")
}
+ // remove any unnecessary whitespace now
+ content = strings.TrimSpace(content)
+
fields := strings.Fields(content)
if len(fields) < 2 {
return "", errors.New("too less fields")
@@ -374,6 +377,11 @@ func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error {
break
}
}
+
+ if !isFound {
+ log.Warn("SSH key %d not found in authorized_keys file for deletion", key.ID)
+ }
+
return nil
}
diff --git a/models/user.go b/models/user.go
index 5c43a23a..23ed5ae8 100644
--- a/models/user.go
+++ b/models/user.go
@@ -16,7 +16,6 @@ import (
_ "image/jpeg"
"image/png"
"os"
- "path"
"path/filepath"
"strings"
"time"
@@ -211,7 +210,7 @@ func (u *User) GenerateRandomAvatar() error {
if err != nil {
return fmt.Errorf("RandomImage: %v", err)
}
- if err = os.MkdirAll(path.Dir(u.CustomAvatarPath()), os.ModePerm); err != nil {
+ if err = os.MkdirAll(filepath.Dir(u.CustomAvatarPath()), os.ModePerm); err != nil {
return fmt.Errorf("MkdirAll: %v", err)
}
fw, err := os.Create(u.CustomAvatarPath())
@@ -599,7 +598,12 @@ func ChangeUserName(u *User, newUserName string) (err error) {
return ErrUserAlreadyExist{newUserName}
}
- return os.Rename(UserPath(u.LowerName), UserPath(newUserName))
+ err = ChangeUsernameInPullRequests(u.Name, newUserName)
+ if err != nil {
+ return fmt.Errorf("ChangeUsernameInPullRequests: %v", err)
+ }
+
+ return os.Rename(UserPath(u.Name), UserPath(newUserName))
}
func updateUser(e Engine, u *User) error {
diff --git a/models/webhook.go b/models/webhook.go
index f58cfbf5..27ac75fe 100644
--- a/models/webhook.go
+++ b/models/webhook.go
@@ -285,7 +285,7 @@ type HookTask struct {
HookID int64
UUID string
Type HookTaskType
- URL string
+ URL string `xorm:"TEXT"`
api.Payloader `xorm:"-"`
PayloadContent string `xorm:"TEXT"`
ContentType HookContentType