diff options
Diffstat (limited to 'models')
-rw-r--r-- | models/error.go | 43 | ||||
-rw-r--r-- | models/git_diff.go | 61 | ||||
-rw-r--r-- | models/org.go | 106 | ||||
-rw-r--r-- | models/pull.go | 17 | ||||
-rw-r--r-- | models/repo.go | 45 | ||||
-rw-r--r-- | models/repo_branch.go | 57 | ||||
-rw-r--r-- | models/ssh_key.go | 8 | ||||
-rw-r--r-- | models/user.go | 10 | ||||
-rw-r--r-- | models/webhook.go | 2 |
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 |