summaryrefslogtreecommitdiffstats
path: root/models
diff options
context:
space:
mode:
Diffstat (limited to 'models')
-rw-r--r--models/access.go27
-rw-r--r--models/action.go4
-rw-r--r--models/error.go18
-rw-r--r--models/fixtures/access_token.yml23
-rw-r--r--models/fixtures/update_task.yml20
-rw-r--r--models/git_diff.go16
-rw-r--r--models/git_diff_test.go16
-rw-r--r--models/graph.go14
-rw-r--r--models/graph_test.go30
-rw-r--r--models/issue.go4
-rw-r--r--models/issue_label.go2
-rw-r--r--models/issue_mail.go2
-rw-r--r--models/migrations/migrations.go4
-rw-r--r--models/migrations/v15.go30
-rw-r--r--models/models.go31
-rw-r--r--models/notification.go2
-rw-r--r--models/org.go6
-rw-r--r--models/pull.go16
-rw-r--r--models/release.go74
-rw-r--r--models/repo.go13
-rw-r--r--models/repo_mirror.go2
-rw-r--r--models/setup_for_test.go47
-rw-r--r--models/ssh_key.go4
-rw-r--r--models/token_test.go107
-rw-r--r--models/update_test.go124
-rw-r--r--models/user.go32
-rw-r--r--models/user_mail.go4
-rw-r--r--models/webhook_slack.go4
28 files changed, 571 insertions, 105 deletions
diff --git a/models/access.go b/models/access.go
index c77e7f0a16..49a8838ea6 100644
--- a/models/access.go
+++ b/models/access.go
@@ -96,28 +96,31 @@ func HasAccess(user *User, repo *Repository, testMode AccessMode) (bool, error)
return hasAccess(x, user, repo, testMode)
}
+type repoAccess struct {
+ Access `xorm:"extends"`
+ Repository `xorm:"extends"`
+}
+
+func (repoAccess) TableName() string {
+ return "access"
+}
+
// GetRepositoryAccesses finds all repositories with their access mode where a user has access but does not own.
func (user *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) {
- accesses := make([]*Access, 0, 10)
- type RepoAccess struct {
- Access `xorm:"extends"`
- Repository `xorm:"extends"`
- }
-
rows, err := x.
- Join("INNER", "repository", "respository.id = access.repo_id").
+ Join("INNER", "repository", "repository.id = access.repo_id").
Where("access.user_id = ?", user.ID).
And("repository.owner_id <> ?", user.ID).
- Rows(new(RepoAccess))
+ Rows(new(repoAccess))
if err != nil {
return nil, err
}
defer rows.Close()
- var repos = make(map[*Repository]AccessMode, len(accesses))
- var ownerCache = make(map[int64]*User, len(accesses))
+ var repos = make(map[*Repository]AccessMode, 10)
+ var ownerCache = make(map[int64]*User, 10)
for rows.Next() {
- var repo RepoAccess
+ var repo repoAccess
err = rows.Scan(&repo)
if err != nil {
return nil, err
@@ -163,7 +166,7 @@ func maxAccessMode(modes ...AccessMode) AccessMode {
return max
}
-// FIXME: do corss-comparison so reduce deletions and additions to the minimum?
+// FIXME: do cross-comparison so reduce deletions and additions to the minimum?
func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]AccessMode) (err error) {
minMode := AccessModeRead
if !repo.IsPrivate {
diff --git a/models/action.go b/models/action.go
index f84d42d0cb..8b3d82b4d6 100644
--- a/models/action.go
+++ b/models/action.go
@@ -145,7 +145,7 @@ func (a *Action) GetRepoPath() string {
}
// ShortRepoPath returns the virtual path to the action repository
-// trimed to max 20 + 1 + 33 chars.
+// trimmed to max 20 + 1 + 33 chars.
func (a *Action) ShortRepoPath() string {
return path.Join(a.ShortRepoUserName(), a.ShortRepoName())
}
@@ -418,7 +418,7 @@ func UpdateIssuesCommit(doer *User, repo *Repository, commits []*PushCommit) err
}
}
- // It is conflict to have close and reopen at same time, so refsMarkd doesn't need to reinit here.
+ // It is conflict to have close and reopen at same time, so refsMarked doesn't need to reinit here.
for _, ref := range issueReopenKeywordsPat.FindAllString(c.Message, -1) {
ref = ref[strings.IndexByte(ref, byte(' '))+1:]
ref = strings.TrimRightFunc(ref, issueIndexTrimRight)
diff --git a/models/error.go b/models/error.go
index d11a9eeb1f..edbb6003e9 100644
--- a/models/error.go
+++ b/models/error.go
@@ -123,6 +123,20 @@ func (err ErrUserHasOrgs) Error() string {
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
}
+// ErrUserNotAllowedCreateOrg represents a "UserNotAllowedCreateOrg" kind of error.
+type ErrUserNotAllowedCreateOrg struct {
+}
+
+// IsErrUserNotAllowedCreateOrg checks if an error is an ErrUserNotAllowedCreateOrg.
+func IsErrUserNotAllowedCreateOrg(err error) bool {
+ _, ok := err.(ErrUserNotAllowedCreateOrg)
+ return ok
+}
+
+func (err ErrUserNotAllowedCreateOrg) Error() string {
+ return fmt.Sprintf("user is not allowed to create organizations")
+}
+
// ErrReachLimitOfRepo represents a "ReachLimitOfRepo" kind of error.
type ErrReachLimitOfRepo struct {
Limit int
@@ -569,7 +583,7 @@ type ErrPullRequestNotExist struct {
IssueID int64
HeadRepoID int64
BaseRepoID int64
- HeadBarcnh string
+ HeadBranch string
BaseBranch string
}
@@ -581,7 +595,7 @@ func IsErrPullRequestNotExist(err error) bool {
func (err ErrPullRequestNotExist) Error() string {
return fmt.Sprintf("pull request does not exist [id: %d, issue_id: %d, head_repo_id: %d, base_repo_id: %d, head_branch: %s, base_branch: %s]",
- err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBarcnh, err.BaseBranch)
+ err.ID, err.IssueID, err.HeadRepoID, err.BaseRepoID, err.HeadBranch, err.BaseBranch)
}
// ErrPullRequestAlreadyExists represents a "PullRequestAlreadyExists"-error
diff --git a/models/fixtures/access_token.yml b/models/fixtures/access_token.yml
new file mode 100644
index 0000000000..9572709dd9
--- /dev/null
+++ b/models/fixtures/access_token.yml
@@ -0,0 +1,23 @@
+-
+ id: 1
+ uid: 1
+ name: Token A
+ sha1: hash1
+ created_unix: 946687980
+ updated_unix: 946687980
+
+-
+ id: 2
+ uid: 1
+ name: Token B
+ sha1: hash2
+ created_unix: 946687980
+ updated_unix: 946687980
+
+-
+ id: 3
+ uid: 2
+ name: Token A
+ sha1: hash3
+ created_unix: 946687980
+ updated_unix: 946687980
diff --git a/models/fixtures/update_task.yml b/models/fixtures/update_task.yml
new file mode 100644
index 0000000000..ffcd5fd6fa
--- /dev/null
+++ b/models/fixtures/update_task.yml
@@ -0,0 +1,20 @@
+-
+ id: 1
+ uuid: uuid1
+ ref_name: refName1
+ old_commit_id: oldCommitId1
+ new_commit_id: newCommitId1
+
+-
+ id: 2
+ uuid: uuid2
+ ref_name: refName2
+ old_commit_id: oldCommitId2
+ new_commit_id: newCommitId2
+
+-
+ id: 3
+ uuid: uuid3
+ ref_name: refName3
+ old_commit_id: oldCommitId3
+ new_commit_id: newCommitId3
diff --git a/models/git_diff.go b/models/git_diff.go
index f796f286d6..eb88d210d4 100644
--- a/models/git_diff.go
+++ b/models/git_diff.go
@@ -78,7 +78,7 @@ var (
func diffToHTML(diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTML {
buf := bytes.NewBuffer(nil)
- // Reproduce signs which are cutted for inline diff before.
+ // Reproduce signs which are cut for inline diff before.
switch lineType {
case DiffLineAdd:
buf.WriteByte('+')
@@ -234,7 +234,7 @@ const cmdDiffHead = "diff --git "
// ParsePatch builds a Diff object from a io.Reader and some
// parameters.
// TODO: move this function to gogits/git-module
-func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*Diff, error) {
+func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*Diff, error) {
var (
diff = &Diff{Files: make([]*DiffFile, 0)}
@@ -295,8 +295,8 @@ func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*
curFileLinesCount++
lineCount++
- // Diff data too large, we only show the first about maxlines lines
- if curFileLinesCount >= maxLines || len(line) >= maxLineCharacteres {
+ // Diff data too large, we only show the first about maxLines lines
+ if curFileLinesCount >= maxLines || len(line) >= maxLineCharacters {
curFile.IsIncomplete = true
}
@@ -447,7 +447,7 @@ func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*
// GetDiffRange builds a Diff between two commits of a repository.
// passing the empty string as beforeCommitID returns a diff from the
// parent commit.
-func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
+func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacters, maxFiles int) (*Diff, error) {
gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
return nil, err
@@ -486,7 +486,7 @@ func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxL
pid := process.Add(fmt.Sprintf("GetDiffRange [repo_path: %s]", repoPath), cmd)
defer process.Remove(pid)
- diff, err := ParsePatch(maxLines, maxLineCharacteres, maxFiles, stdout)
+ diff, err := ParsePatch(maxLines, maxLineCharacters, maxFiles, stdout)
if err != nil {
return nil, fmt.Errorf("ParsePatch: %v", err)
}
@@ -554,6 +554,6 @@ func GetRawDiff(repoPath, commitID string, diffType RawDiffType, writer io.Write
}
// GetDiffCommit builds a Diff representing the given commitID.
-func GetDiffCommit(repoPath, commitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
- return GetDiffRange(repoPath, "", commitID, maxLines, maxLineCharacteres, maxFiles)
+func GetDiffCommit(repoPath, commitID string, maxLines, maxLineCharacters, maxFiles int) (*Diff, error) {
+ return GetDiffRange(repoPath, "", commitID, maxLines, maxLineCharacters, maxFiles)
}
diff --git a/models/git_diff_test.go b/models/git_diff_test.go
index cf98f65399..f88e6fb610 100644
--- a/models/git_diff_test.go
+++ b/models/git_diff_test.go
@@ -20,16 +20,16 @@ func assertLineEqual(t *testing.T, d1 *DiffLine, d2 *DiffLine) {
func TestDiffToHTML(t *testing.T) {
assertEqual(t, "+foo <span class=\"added-code\">bar</span> biz", diffToHTML([]dmp.Diff{
- dmp.Diff{dmp.DiffEqual, "foo "},
- dmp.Diff{dmp.DiffInsert, "bar"},
- dmp.Diff{dmp.DiffDelete, " baz"},
- dmp.Diff{dmp.DiffEqual, " biz"},
+ {dmp.DiffEqual, "foo "},
+ {dmp.DiffInsert, "bar"},
+ {dmp.DiffDelete, " baz"},
+ {dmp.DiffEqual, " biz"},
}, DiffLineAdd))
assertEqual(t, "-foo <span class=\"removed-code\">bar</span> biz", diffToHTML([]dmp.Diff{
- dmp.Diff{dmp.DiffEqual, "foo "},
- dmp.Diff{dmp.DiffDelete, "bar"},
- dmp.Diff{dmp.DiffInsert, " baz"},
- dmp.Diff{dmp.DiffEqual, " biz"},
+ {dmp.DiffEqual, "foo "},
+ {dmp.DiffDelete, "bar"},
+ {dmp.DiffInsert, " baz"},
+ {dmp.DiffEqual, " biz"},
}, DiffLineDel))
}
diff --git a/models/graph.go b/models/graph.go
index 973476a746..7413f409de 100644
--- a/models/graph.go
+++ b/models/graph.go
@@ -31,7 +31,7 @@ type GraphItems []GraphItem
// GetCommitGraph return a list of commit (GraphItems) from all branches
func GetCommitGraph(r *git.Repository) (GraphItems, error) {
- var Commitgraph []GraphItem
+ var CommitGraph []GraphItem
format := "DATA:|%d|%H|%ad|%an|%ae|%h|%s"
@@ -47,19 +47,19 @@ func GetCommitGraph(r *git.Repository) (GraphItems, error) {
)
graph, err := graphCmd.RunInDir(r.Path)
if err != nil {
- return Commitgraph, err
+ return CommitGraph, err
}
- Commitgraph = make([]GraphItem, 0, 100)
+ CommitGraph = make([]GraphItem, 0, 100)
for _, s := range strings.Split(graph, "\n") {
GraphItem, err := graphItemFromString(s, r)
if err != nil {
- return Commitgraph, err
+ return CommitGraph, err
}
- Commitgraph = append(Commitgraph, GraphItem)
+ CommitGraph = append(CommitGraph, GraphItem)
}
- return Commitgraph, nil
+ return CommitGraph, nil
}
func graphItemFromString(s string, r *git.Repository) (GraphItem, error) {
@@ -102,7 +102,7 @@ func graphItemFromString(s string, r *git.Repository) (GraphItem, error) {
rows[5],
rows[6],
rows[7],
- len(rows[2]) == 0, // no commits refered to, only relation in current line.
+ len(rows[2]) == 0, // no commits referred to, only relation in current line.
}
return gi, nil
}
diff --git a/models/graph_test.go b/models/graph_test.go
index 23d8aa8492..47c9dbb084 100644
--- a/models/graph_test.go
+++ b/models/graph_test.go
@@ -17,25 +17,29 @@ func BenchmarkGetCommitGraph(b *testing.B) {
b.Error("Could not open repository")
}
- graph, err := GetCommitGraph(currentRepo)
- if err != nil {
- b.Error("Could get commit graph")
- }
-
- if len(graph) < 100 {
- b.Error("Should get 100 log lines.")
+ for i := 0; i < b.N; i++ {
+ graph, err := GetCommitGraph(currentRepo)
+ if err != nil {
+ b.Error("Could get commit graph")
+ }
+
+ if len(graph) < 100 {
+ b.Error("Should get 100 log lines.")
+ }
}
}
func BenchmarkParseCommitString(b *testing.B) {
testString := "* DATA:||4e61bacab44e9b4730e44a6615d04098dd3a8eaf|2016-12-20 21:10:41 +0100|Kjell Kvinge|kjell@kvinge.biz|4e61bac|Add route for graph"
- graphItem, err := graphItemFromString(testString, nil)
- if err != nil {
- b.Error("could not parse teststring")
- }
+ for i := 0; i < b.N; i++ {
+ graphItem, err := graphItemFromString(testString, nil)
+ if err != nil {
+ b.Error("could not parse teststring")
+ }
- if graphItem.Author != "Kjell Kvinge" {
- b.Error("Did not get expected data")
+ if graphItem.Author != "Kjell Kvinge" {
+ b.Error("Did not get expected data")
+ }
}
}
diff --git a/models/issue.go b/models/issue.go
index 6303911808..315c91e159 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -1202,8 +1202,8 @@ func GetIssueStats(opts *IssueStatsOptions) *IssueStats {
if opts.MentionedID > 0 {
sess.Join("INNER", "issue_user", "issue.id = issue_user.issue_id").
- And("issue_user.uid = ?", opts.MentionedID).
- And("issue_user.is_mentioned = ?", true)
+ And("issue_user.uid = ?", opts.MentionedID).
+ And("issue_user.is_mentioned = ?", true)
}
return sess
diff --git a/models/issue_label.go b/models/issue_label.go
index f06f0f97c3..0e1c6d6c4e 100644
--- a/models/issue_label.go
+++ b/models/issue_label.go
@@ -259,7 +259,7 @@ func DeleteLabel(repoID, labelID int64) error {
// |___/____ >____ >____/ \___ >_______ (____ /___ /\___ >____/
// \/ \/ \/ \/ \/ \/ \/
-// IssueLabel represetns an issue-lable relation.
+// IssueLabel represents an issue-label relation.
type IssueLabel struct {
ID int64 `xorm:"pk autoincr"`
IssueID int64 `xorm:"UNIQUE(s)"`
diff --git a/models/issue_mail.go b/models/issue_mail.go
index 88adda5619..4b076606bf 100644
--- a/models/issue_mail.go
+++ b/models/issue_mail.go
@@ -24,7 +24,7 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string)
return nil
}
- // Mail wahtcers.
+ // Mail watchers.
watchers, err := GetWatchers(issue.RepoID)
if err != nil {
return fmt.Errorf("GetWatchers [%d]: %v", issue.RepoID, err)
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 66f80dac30..69408a071d 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -76,8 +76,10 @@ var migrations = []Migration{
// v13 -> v14:v0.9.87
NewMigration("set comment updated with created", setCommentUpdatedWithCreated),
-
+ // v14
NewMigration("create user column diff view style", createUserColumnDiffViewStyle),
+ // v15
+ NewMigration("create user column allow create organization", createAllowCreateOrganizationColumn),
}
// Migrate database to current version
diff --git a/models/migrations/v15.go b/models/migrations/v15.go
new file mode 100644
index 0000000000..90fc22c6d3
--- /dev/null
+++ b/models/migrations/v15.go
@@ -0,0 +1,30 @@
+// Copyright 2016 Gitea. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+ "fmt"
+
+ "github.com/go-xorm/xorm"
+)
+
+// UserV15 describes the added field for User
+type UserV15 struct {
+ AllowCreateOrganization bool
+}
+
+// TableName will be invoked by XORM to customrize the table name
+func (*UserV15) TableName() string {
+ return "user"
+}
+
+func createAllowCreateOrganizationColumn(x *xorm.Engine) error {
+ if err := x.Sync2(new(UserV15)); err != nil {
+ return fmt.Errorf("Sync2: %v", err)
+ } else if _, err = x.Where("type=0").Cols("allow_create_organization").Update(&UserV15{AllowCreateOrganization: true}); err != nil {
+ return fmt.Errorf("set allow_create_organization: %v", err)
+ }
+ return nil
+}
diff --git a/models/models.go b/models/models.go
index 1bebaa602c..131fd4fdb2 100644
--- a/models/models.go
+++ b/models/models.go
@@ -156,15 +156,15 @@ func parsePostgreSQLHostPort(info string) (string, string) {
func parseMSSQLHostPort(info string) (string, string) {
host, port := "127.0.0.1", "1433"
- if strings.Contains(info, ":") {
- host = strings.Split(info, ":")[0]
- port = strings.Split(info, ":")[1]
- } else if strings.Contains(info, ",") {
- host = strings.Split(info, ",")[0]
- port = strings.TrimSpace(strings.Split(info, ",")[1])
- } else if len(info) > 0 {
- host = info
- }
+ if strings.Contains(info, ":") {
+ host = strings.Split(info, ":")[0]
+ port = strings.Split(info, ":")[1]
+ } else if strings.Contains(info, ",") {
+ host = strings.Split(info, ",")[0]
+ port = strings.TrimSpace(strings.Split(info, ",")[1])
+ } else if len(info) > 0 {
+ host = info
+ }
return host, port
}
@@ -319,7 +319,14 @@ func Ping() error {
return x.Ping()
}
-// DumpDatabase dumps all data from database to file system.
-func DumpDatabase(filePath string) error {
- return x.DumpAllToFile(filePath)
+// DumpDatabase dumps all data from database according the special database SQL syntax to file system.
+func DumpDatabase(filePath string, dbType string) error {
+ var tbs []*core.Table
+ for _, t := range tables {
+ tbs = append(tbs, x.TableInfo(t).Table)
+ }
+ if len(dbType) > 0 {
+ return x.DumpTablesToFile(tbs, filePath, core.DbType(dbType))
+ }
+ return x.DumpTablesToFile(tbs, filePath)
}
diff --git a/models/notification.go b/models/notification.go
index 188c987536..e2460e8369 100644
--- a/models/notification.go
+++ b/models/notification.go
@@ -66,7 +66,7 @@ func (n *Notification) BeforeInsert() {
n.UpdatedUnix = nowUnix
}
-// BeforeUpdate runs while updateing a record
+// BeforeUpdate runs while updating a record
func (n *Notification) BeforeUpdate() {
var (
now = time.Now()
diff --git a/models/org.go b/models/org.go
index 172295e7ae..7fbd790f5b 100644
--- a/models/org.go
+++ b/models/org.go
@@ -97,6 +97,10 @@ func (org *User) RemoveOrgRepo(repoID int64) error {
// CreateOrganization creates record of a new organization.
func CreateOrganization(org, owner *User) (err error) {
+ if !owner.CanCreateOrganization() {
+ return ErrUserNotAllowedCreateOrg{}
+ }
+
if err = IsUsableUsername(org.Name); err != nil {
return err
}
@@ -555,7 +559,7 @@ func (org *User) GetUserRepositories(userID int64, page, pageSize int) ([]*Repos
}
repos := make([]*Repository, 0, pageSize)
- if err := x.
+ if err := x.Select("`repository`.*").
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
Where(cond).
GroupBy("`repository`.id").
diff --git a/models/pull.go b/models/pull.go
index 36194d8660..6231b71cb7 100644
--- a/models/pull.go
+++ b/models/pull.go
@@ -372,7 +372,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
// TODO: when squash commits, no need to append merge commit.
// It is possible that head branch is not fully sync with base branch for merge commits,
- // so we need to get latest head commit and append merge commit manully
+ // so we need to get latest head commit and append merge commit manually
// to avoid strange diff commits produced.
mergeCommit, err := baseGitRepo.GetBranchCommit(pr.BaseBranch)
if err != nil {
@@ -419,9 +419,9 @@ func (pr *PullRequest) testPatch() (err error) {
return fmt.Errorf("BaseRepo.PatchPath: %v", err)
}
- // Fast fail if patch does not exist, this assumes data is cruppted.
+ // Fast fail if patch does not exist, this assumes data is corrupted.
if !com.IsFile(patchPath) {
- log.Trace("PullRequest[%d].testPatch: ignored cruppted data", pr.ID)
+ log.Trace("PullRequest[%d].testPatch: ignored corrupted data", pr.ID)
return nil
}
@@ -573,7 +573,7 @@ func PullRequests(baseRepoID int64, opts *PullRequestsOptions) ([]*PullRequest,
return prs, maxResults, findSession.Find(&prs)
}
-// GetUnmergedPullRequest returnss a pull request that is open and has not been merged
+// GetUnmergedPullRequest returns a pull request that is open and has not been merged
// by given head/base and repo/branch.
func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch string) (*PullRequest, error) {
pr := new(PullRequest)
@@ -591,7 +591,7 @@ func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch
return pr, nil
}
-// GetUnmergedPullRequestsByHeadInfo returnss all pull requests that are open and has not been merged
+// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
// by given head information (repo and branch).
func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) {
prs := make([]*PullRequest, 0, 2)
@@ -602,7 +602,7 @@ func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequ
Find(&prs)
}
-// GetUnmergedPullRequestsByBaseInfo returnss all pull requests that are open and has not been merged
+// GetUnmergedPullRequestsByBaseInfo returns all pull requests that are open and has not been merged
// by given base information (repo and branch).
func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequest, error) {
prs := make([]*PullRequest, 0, 2)
@@ -885,7 +885,7 @@ func ChangeUsernameInPullRequests(oldUserName, newUserName string) error {
return err
}
-// checkAndUpdateStatus checks if pull request is possible to levaing checking status,
+// checkAndUpdateStatus checks if pull request is possible to leaving checking status,
// and set to be either conflict or mergeable.
func (pr *PullRequest) checkAndUpdateStatus() {
// Status is not changed to conflict means mergeable.
@@ -893,7 +893,7 @@ func (pr *PullRequest) checkAndUpdateStatus() {
pr.Status = PullRequestStatusMergeable
}
- // Make sure there is no waiting test to process before levaing the checking status.
+ // Make sure there is no waiting test to process before leaving the checking status.
if !pullRequestQueue.Exist(pr.ID) {
if err := pr.UpdateCols("status"); err != nil {
log.Error(4, "Update[%d]: %v", pr.ID, err)
diff --git a/models/release.go b/models/release.go
index 41fd145bea..428b79e45f 100644
--- a/models/release.go
+++ b/models/release.go
@@ -15,12 +15,16 @@ import (
"code.gitea.io/git"
"code.gitea.io/gitea/modules/process"
+ "code.gitea.io/gitea/modules/setting"
+
+ api "code.gitea.io/sdk/gitea"
)
// Release represents a release of repository.
type Release struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64
+ Repo *Repository `xorm:"-"`
PublisherID int64
Publisher *User `xorm:"-"`
TagName string
@@ -53,6 +57,62 @@ func (r *Release) AfterSet(colName string, _ xorm.Cell) {
}
}
+func (r *Release) loadAttributes(e Engine) error {
+ var err error
+ if r.Repo == nil {
+ r.Repo, err = GetRepositoryByID(r.RepoID)
+ if err != nil {
+ return err
+ }
+ }
+ if r.Publisher == nil {
+ r.Publisher, err = GetUserByID(r.PublisherID)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// LoadAttributes load repo and publisher attributes for a realease
+func (r *Release) LoadAttributes() error {
+ return r.loadAttributes(x)
+}
+
+// APIURL the api url for a release. release must have attributes loaded
+func (r *Release) APIURL() string {
+ return fmt.Sprintf("%sapi/v1/%s/releases/%d",
+ setting.AppURL, r.Repo.FullName(), r.ID)
+}
+
+// ZipURL the zip url for a release. release must have attributes loaded
+func (r *Release) ZipURL() string {
+ return fmt.Sprintf("%s/archive/%s.zip", r.Repo.HTMLURL(), r.TagName)
+}
+
+// TarURL the tar.gz url for a release. release must have attributes loaded
+func (r *Release) TarURL() string {
+ return fmt.Sprintf("%s/archive/%s.tar.gz", r.Repo.HTMLURL(), r.TagName)
+}
+
+// APIFormat convert a Release to api.Release
+func (r *Release) APIFormat() *api.Release {
+ return &api.Release{
+ ID: r.ID,
+ TagName: r.TagName,
+ Target: r.Target,
+ Note: r.Note,
+ URL: r.APIURL(),
+ TarURL: r.TarURL(),
+ ZipURL: r.ZipURL(),
+ IsDraft: r.IsDraft,
+ IsPrerelease: r.IsPrerelease,
+ CreatedAt: r.Created,
+ PublishedAt: r.Created,
+ Publisher: r.Publisher.APIFormat(),
+ }
+}
+
// IsReleaseExist returns true if release with given tag name already exists.
func IsReleaseExist(repoID int64, tagName string) (bool, error) {
if len(tagName) == 0 {
@@ -189,7 +249,7 @@ func UpdateRelease(gitRepo *git.Repository, rel *Release) (err error) {
}
// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
-func DeleteReleaseByID(id int64, u *User) error {
+func DeleteReleaseByID(id int64, u *User, delTag bool) error {
rel, err := GetReleaseByID(id)
if err != nil {
return fmt.Errorf("GetReleaseByID: %v", err)
@@ -207,11 +267,13 @@ func DeleteReleaseByID(id int64, u *User) error {
return fmt.Errorf("DeleteReleaseByID: permission denied")
}
- _, stderr, err := process.ExecDir(-1, repo.RepoPath(),
- fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID),
- "git", "tag", "-d", rel.TagName)
- if err != nil && !strings.Contains(stderr, "not found") {
- return fmt.Errorf("git tag -d: %v - %s", err, stderr)
+ if delTag {
+ _, stderr, err := process.ExecDir(-1, repo.RepoPath(),
+ fmt.Sprintf("DeleteReleaseByID (git tag -d): %d", rel.ID),
+ "git", "tag", "-d", rel.TagName)
+ if err != nil && !strings.Contains(stderr, "not found") {
+ return fmt.Errorf("git tag -d: %v - %s", err, stderr)
+ }
}
if _, err = x.Id(rel.ID).Delete(new(Release)); err != nil {
diff --git a/models/repo.go b/models/repo.go
index ce9740f8c4..85807e3a4b 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -259,7 +259,7 @@ func (repo *Repository) AfterSet(colName string, _ xorm.Cell) {
// MustOwner always returns a valid *User object to avoid
// conceptually impossible error handling.
-// It creates a fake object that contains error deftail
+// It creates a fake object that contains error details
// when error occurs.
func (repo *Repository) MustOwner() *User {
return repo.mustOwner(x)
@@ -691,7 +691,6 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
wikiRemotePath := wikiRemoteURL(opts.RemoteAddr)
if len(wikiRemotePath) > 0 {
-
if err := os.RemoveAll(wikiPath); err != nil {
return repo, fmt.Errorf("Fail to remove %s: %v", wikiPath, err)
}
@@ -700,8 +699,12 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
Mirror: true,
Quiet: true,
Timeout: migrateTimeout,
+ Branch: "master",
}); err != nil {
- log.Info("Clone wiki: %v", err)
+ log.Warn("Clone wiki: %v", err)
+ if err := os.RemoveAll(wikiPath); err != nil {
+ return repo, fmt.Errorf("Fail to remove %s: %v", wikiPath, err)
+ }
}
}
@@ -851,7 +854,7 @@ func getRepoInitFile(tp, name string) ([]byte, error) {
}
func prepareRepoCommit(repo *Repository, tmpDir, repoPath string, opts CreateRepoOptions) error {
- // Clone to temprory path and do the init commit.
+ // Clone to temporary path and do the init commit.
_, stderr, err := process.Exec(
fmt.Sprintf("initRepository(git clone): %s", repoPath), "git", "clone", repoPath, tmpDir)
if err != nil {
@@ -1324,7 +1327,7 @@ func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err e
return fmt.Errorf("getOwner: %v", err)
}
if repo.Owner.IsOrganization() {
- // Organization repository need to recalculate access table when visivility is changed.
+ // Organization repository need to recalculate access table when visibility is changed.
if err = repo.recalculateTeamAccesses(e, 0); err != nil {
return fmt.Errorf("recalculateTeamAccesses: %v", err)
}
diff --git a/models/repo_mirror.go b/models/repo_mirror.go
index b834a6e5cd..2cedf69d70 100644
--- a/models/repo_mirror.go
+++ b/models/repo_mirror.go
@@ -247,7 +247,7 @@ func SyncMirrors() {
}
}
-// InitSyncMirrors initializes a go routine to sync the mirros
+// InitSyncMirrors initializes a go routine to sync the mirrors
func InitSyncMirrors() {
go SyncMirrors()
}
diff --git a/models/setup_for_test.go b/models/setup_for_test.go
new file mode 100644
index 0000000000..b585a7490e
--- /dev/null
+++ b/models/setup_for_test.go
@@ -0,0 +1,47 @@
+// Copyright 2016 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package models
+
+import (
+ "fmt"
+ "os"
+ "testing"
+
+ "github.com/go-xorm/core"
+ "github.com/go-xorm/xorm"
+ _ "github.com/mattn/go-sqlite3" // for the test engine
+ "gopkg.in/testfixtures.v2"
+)
+
+func TestMain(m *testing.M) {
+ if err := CreateTestEngine(); err != nil {
+ fmt.Printf("Error creating test engine: %v\n", err)
+ os.Exit(1)
+ }
+ os.Exit(m.Run())
+}
+
+var fixtures *testfixtures.Context
+
+// CreateTestEngine create an xorm engine for testing
+func CreateTestEngine() error {
+ testfixtures.SkipDatabaseNameCheck(true)
+ var err error
+ x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
+ if err != nil {
+ return err
+ }
+ x.SetMapper(core.GonicMapper{})
+ if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
+ return err
+ }
+ fixtures, err = testfixtures.NewFolder(x.DB().DB, &testfixtures.SQLite{}, "fixtures/")
+ return err
+}
+
+// PrepareTestDatabase load test fixtures into test database
+func PrepareTestDatabase() error {
+ return fixtures.Load()
+}
diff --git a/models/ssh_key.go b/models/ssh_key.go
index d7d71f68cb..cdb83b44e0 100644
--- a/models/ssh_key.go
+++ b/models/ssh_key.go
@@ -354,7 +354,7 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error {
return nil
}
-// checkKeyContent onlys checks if key content has been used as public key,
+// checkKeyContent only checks if key content has been used as public key,
// it is OK to use same key as deploy key for multiple repositories/users.
func checkKeyContent(content string) error {
has, err := x.Get(&PublicKey{
@@ -526,7 +526,7 @@ func DeletePublicKey(doer *User, id int64) (err error) {
// RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again.
// Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
-// outsite any session scope independently.
+// outside any session scope independently.
func RewriteAllPublicKeys() error {
sshOpLocker.Lock()
defer sshOpLocker.Unlock()
diff --git a/models/token_test.go b/models/token_test.go
new file mode 100644
index 0000000000..15207ceb65
--- /dev/null
+++ b/models/token_test.go
@@ -0,0 +1,107 @@
+// Copyright 2016 The Gitea 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 (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestNewAccessToken(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ token := &AccessToken{
+ UID: 3,
+ Name: "Token C",
+ }
+ assert.NoError(t, NewAccessToken(token))
+ sess := x.NewSession()
+ defer sess.Close()
+ has, err := sess.Get(*token)
+ assert.NoError(t, err)
+ assert.True(t, has)
+ assert.Equal(t, int64(3), token.UID)
+ assert.Equal(t, "Token C", token.Name)
+
+ invalidToken := &AccessToken{
+ ID: token.ID, // duplicate
+ UID: 2,
+ Name: "Token F",
+ }
+ assert.Error(t, NewAccessToken(invalidToken))
+}
+
+func TestGetAccessTokenBySHA(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ token, err := GetAccessTokenBySHA("hash1")
+ assert.NoError(t, err)
+ assert.Equal(t, int64(1), token.UID)
+ assert.Equal(t, "Token A", token.Name)
+ assert.Equal(t, "hash1", token.Sha1)
+
+ token, err = GetAccessTokenBySHA("notahash")
+ assert.Error(t, err)
+ assert.True(t, IsErrAccessTokenNotExist(err))
+
+ token, err = GetAccessTokenBySHA("")
+ assert.Error(t, err)
+ assert.True(t, IsErrAccessTokenEmpty(err))
+}
+
+func TestListAccessTokens(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ tokens, err := ListAccessTokens(1)
+ assert.NoError(t, err)
+ assert.Len(t, tokens, 2)
+ assert.Equal(t, int64(1), tokens[0].UID)
+ assert.Equal(t, int64(1), tokens[1].UID)
+ assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token A")
+ assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token B")
+
+ tokens, err = ListAccessTokens(2)
+ assert.NoError(t, err)
+ assert.Len(t, tokens, 1)
+ assert.Equal(t, int64(2), tokens[0].UID)
+ assert.Equal(t, "Token A", tokens[0].Name)
+
+ tokens, err = ListAccessTokens(100)
+ assert.NoError(t, err)
+ assert.Empty(t, tokens)
+}
+
+func TestUpdateAccessToken(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ token, err := GetAccessTokenBySHA("hash2")
+ assert.NoError(t, err)
+ token.Name = "Token Z"
+
+ assert.NoError(t, UpdateAccessToken(token))
+
+ sess := x.NewSession()
+ defer sess.Close()
+ has, err := sess.Get(token)
+ assert.NoError(t, err)
+ assert.True(t, has)
+ assert.Equal(t, token.Name, "Token Z")
+}
+
+func TestDeleteAccessTokenByID(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+
+ token, err := GetAccessTokenBySHA("hash2")
+ assert.NoError(t, err)
+ assert.Equal(t, int64(1), token.UID)
+
+ assert.NoError(t, DeleteAccessTokenByID(token.ID, 1))
+ sess := x.NewSession()
+ defer sess.Close()
+ has, err := sess.Get(token)
+ assert.NoError(t, err)
+ assert.False(t, has)
+
+ err = DeleteAccessTokenByID(100, 100)
+ assert.Error(t, err)
+ assert.True(t, IsErrAccessTokenNotExist(err))
+}
diff --git a/models/update_test.go b/models/update_test.go
new file mode 100644
index 0000000000..141eb2fd51
--- /dev/null
+++ b/models/update_test.go
@@ -0,0 +1,124 @@
+// Copyright 2016 The Gitea 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 (
+ "container/list"
+ "testing"
+ "time"
+
+ "code.gitea.io/git"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestAddUpdateTask(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ task := &UpdateTask{
+ UUID: "uuid4",
+ RefName: "refName4",
+ OldCommitID: "oldCommitId4",
+ NewCommitID: "newCommitId4",
+ }
+ assert.NoError(t, AddUpdateTask(task))
+
+ sess := x.NewSession()
+ defer sess.Close()
+ has, err := sess.Get(task)
+ assert.NoError(t, err)
+ assert.True(t, has)
+ assert.Equal(t, "uuid4", task.UUID)
+}
+
+func TestGetUpdateTaskByUUID(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ task, err := GetUpdateTaskByUUID("uuid1")
+ assert.NoError(t, err)
+ assert.Equal(t, "uuid1", task.UUID)
+ assert.Equal(t, "refName1", task.RefName)
+ assert.Equal(t, "oldCommitId1", task.OldCommitID)
+ assert.Equal(t, "newCommitId1", task.NewCommitID)
+}
+
+func TestDeleteUpdateTaskByUUID(t *testing.T) {
+ assert.NoError(t, PrepareTestDatabase())
+ assert.NoError(t, DeleteUpdateTaskByUUID("uuid1"))
+ sess := x.NewSession()
+ defer sess.Close()
+ has, err := sess.Get(&UpdateTask{UUID: "uuid1"})
+ assert.NoError(t, err)
+ assert.False(t, has)
+
+ assert.NoError(t, DeleteUpdateTaskByUUID("invalid"))
+}
+
+func TestCommitToPushCommit(t *testing.T) {
+ now := time.Now()
+ sig := &git.Signature{
+ Email: "example@example.com",
+ Name: "John Doe",
+ When: now,
+ }
+ const hexString = "0123456789abcdef0123456789abcdef01234567"
+ sha1, err := git.NewIDFromString(hexString)
+ assert.NoError(t, err)
+ pushCommit := CommitToPushCommit(&git.Commit{
+ ID: sha1,
+ Author: sig,
+ Committer: sig,
+ CommitMessage: "Commit Message",
+ })
+ assert.Equal(t, hexString, pushCommit.Sha1)
+ assert.Equal(t, "Commit Message", pushCommit.Message)
+ assert.Equal(t, "example@example.com", pushCommit.AuthorEmail)
+ assert.Equal(t, "John Doe", pushCommit.AuthorName)
+ assert.Equal(t, "example@example.com", pushCommit.CommitterEmail)
+ assert.Equal(t, "John Doe", pushCommit.CommitterName)
+ assert.Equal(t, now, pushCommit.Timestamp)
+}
+
+func TestListToPushCommits(t *testing.T) {
+ now := time.Now()
+ sig := &git.Signature{
+ Email: "example@example.com",
+ Name: "John Doe",
+ When: now,
+ }
+
+ const hexString1 = "0123456789abcdef0123456789abcdef01234567"
+ hash1, err := git.NewIDFromString(hexString1)
+ assert.NoError(t, err)
+ const hexString2 = "fedcba9876543210fedcba9876543210fedcba98"
+ hash2, err := git.NewIDFromString(hexString2)
+ assert.NoError(t, err)
+
+ l := list.New()
+ l.PushBack(&git.Commit{
+ ID: hash1,
+ Author: sig,
+ Committer: sig,
+ CommitMessage: "Message1",
+ })
+ l.PushBack(&git.Commit{
+ ID: hash2,
+ Author: sig,
+ Committer: sig,
+ CommitMessage: "Message2",
+ })
+
+ pushCommits := ListToPushCommits(l)
+ assert.Equal(t, 2, pushCommits.Len)
+ assert.Equal(t, 2, len(pushCommits.Commits))
+
+ assert.Equal(t, "Message1", pushCommits.Commits[0].Message)
+ assert.Equal(t, hexString1, pushCommits.Commits[0].Sha1)
+ assert.Equal(t, "example@example.com", pushCommits.Commits[0].AuthorEmail)
+ assert.Equal(t, now, pushCommits.Commits[0].Timestamp)
+
+ assert.Equal(t, "Message2", pushCommits.Commits[1].Message)
+ assert.Equal(t, hexString2, pushCommits.Commits[1].Sha1)
+ assert.Equal(t, "example@example.com", pushCommits.Commits[1].AuthorEmail)
+ assert.Equal(t, now, pushCommits.Commits[1].Timestamp)
+}
diff --git a/models/user.go b/models/user.go
index d48397ef7e..1dbd63dce0 100644
--- a/models/user.go
+++ b/models/user.go
@@ -102,11 +102,12 @@ type User struct {
MaxRepoCreation int `xorm:"NOT NULL DEFAULT -1"`
// Permissions
- IsActive bool // Activate primary email
- IsAdmin bool
- AllowGitHook bool
- AllowImportLocal bool // Allow migrate repository by local path
- ProhibitLogin bool
+ IsActive bool // Activate primary email
+ IsAdmin bool
+ AllowGitHook bool
+ AllowImportLocal bool // Allow migrate repository by local path
+ AllowCreateOrganization bool `xorm:"DEFAULT true"`
+ ProhibitLogin bool
// Avatar
Avatar string `xorm:"VARCHAR(2048) NOT NULL"`
@@ -210,6 +211,11 @@ func (u *User) CanCreateRepo() bool {
return u.NumRepos < u.MaxRepoCreation
}
+// CanCreateOrganization returns true if user can create organisation.
+func (u *User) CanCreateOrganization() bool {
+ return u.IsAdmin || u.AllowCreateOrganization
+}
+
// CanEditGitHook returns true if user can edit Git hooks.
func (u *User) CanEditGitHook() bool {
return u.IsAdmin || u.AllowGitHook
@@ -594,6 +600,15 @@ func CreateUser(u *User) (err error) {
}
u.Email = strings.ToLower(u.Email)
+ has, err := x.
+ Where("email=?", u.Email).
+ Get(new(User))
+ if err != nil {
+ return err
+ } else if has {
+ return ErrEmailAlreadyUsed{u.Email}
+ }
+
isExist, err = IsEmailUsed(u.Email)
if err != nil {
return err
@@ -611,6 +626,7 @@ func CreateUser(u *User) (err error) {
return err
}
u.EncodePasswd()
+ u.AllowCreateOrganization = true
u.MaxRepoCreation = -1
sess := x.NewSession()
@@ -656,7 +672,7 @@ func Users(opts *SearchUserOptions) ([]*User, error) {
Find(&users)
}
-// get user by erify code
+// get user by verify code
func getVerifyUser(code string) (user *User) {
if len(code) <= base.TimeLimitCodeLength {
return nil
@@ -1050,7 +1066,7 @@ type UserCommit struct {
*git.Commit
}
-// ValidateCommitWithEmail chceck if author's e-mail of commit is corresponsind to a user.
+// ValidateCommitWithEmail check if author's e-mail of commit is corresponding to a user.
func ValidateCommitWithEmail(c *git.Commit) *User {
u, err := GetUserByEmail(c.Author.Email)
if err != nil {
@@ -1209,7 +1225,7 @@ func FollowUser(userID, followID int64) (err error) {
return sess.Commit()
}
-// UnfollowUser unmarks someone be another's follower.
+// UnfollowUser unmarks someone as another's follower.
func UnfollowUser(userID, followID int64) (err error) {
if userID == followID || !IsFollowing(userID, followID) {
return nil
diff --git a/models/user_mail.go b/models/user_mail.go
index ce29354771..4ccf08e9d9 100644
--- a/models/user_mail.go
+++ b/models/user_mail.go
@@ -49,8 +49,8 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
}
}
- // We alway want the primary email address displayed, even if it's not in
- // the emailaddress table (yet).
+ // We always want the primary email address displayed, even if it's not in
+ // the email address table (yet).
if !isPrimaryFound {
emails = append(emails, &EmailAddress{
Email: u.Email,
diff --git a/models/webhook_slack.go b/models/webhook_slack.go
index aaeef6a001..b297fefd66 100644
--- a/models/webhook_slack.go
+++ b/models/webhook_slack.go
@@ -16,7 +16,7 @@ import (
"code.gitea.io/gitea/modules/setting"
)
-// SlackMeta contains the slack metdata
+// SlackMeta contains the slack metadata
type SlackMeta struct {
Channel string `json:"channel"`
Username string `json:"username"`
@@ -75,7 +75,7 @@ func SlackShortTextFormatter(s string) string {
return s
}
-// SlackLinkFormatter creates a link compatablie with slack
+// SlackLinkFormatter creates a link compatible with slack
func SlackLinkFormatter(url string, text string) string {
return fmt.Sprintf("<%s|%s>", url, SlackTextFormatter(text))
}