aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
authorEmrah URHAN <raxetul@gmail.com>2015-11-22 19:40:18 +0200
committerEmrah URHAN <raxetul@gmail.com>2015-11-22 19:40:18 +0200
commit737da1a3748d7c82af771d3ba4aa4c76ba219eee (patch)
treeb59104944ba28771752adcc1231a847b6704ac4d /models
parentf63a468dfce812423b78a47cfa2583c5ad2faa49 (diff)
parentefaf60ba5a4a7c0954dbaf57203859db3258281f (diff)
Latest develop updates is merged with my RaspberryPi Dockerfile version.
Merge branch 'develop' of https://github.com/gogits/gogs into develop
Diffstat (limited to 'models')
-rw-r--r--models/access.go48
-rw-r--r--models/action.go85
-rw-r--r--models/error.go112
-rw-r--r--models/git_diff.go42
-rw-r--r--models/issue.go22
-rw-r--r--models/login.go7
-rw-r--r--models/migrations/migrations.go53
-rw-r--r--models/models.go2
-rw-r--r--models/publickey.go141
-rw-r--r--models/pull.go66
-rw-r--r--models/release.go83
-rw-r--r--models/repo.go197
-rw-r--r--models/update.go40
-rw-r--r--models/user.go56
-rw-r--r--models/webhook.go4
15 files changed, 685 insertions, 273 deletions
diff --git a/models/access.go b/models/access.go
index fe8bf2c1..5eef3281 100644
--- a/models/access.go
+++ b/models/access.go
@@ -36,19 +36,19 @@ func accessLevel(e Engine, u *User, repo *Repository) (AccessMode, error) {
mode = ACCESS_MODE_READ
}
- if u != nil {
- if u.Id == repo.OwnerID {
- return ACCESS_MODE_OWNER, nil
- }
+ if u == nil {
+ return mode, 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
+ if u.Id == repo.OwnerID {
+ return ACCESS_MODE_OWNER, nil
}
- return mode, 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
}
// AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the
@@ -67,9 +67,8 @@ 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 he/she owns.
-func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) {
+// GetRepositoryAccesses finds all repositories with their access mode where a user has access but does not own.
+func (u *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) {
accesses := make([]*Access, 0, 10)
if err := x.Find(&accesses, &Access{UserID: u.Id}); err != nil {
return nil, err
@@ -80,7 +79,7 @@ func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) {
repo, err := GetRepositoryByID(access.RepoID)
if err != nil {
if IsErrRepoNotExist(err) {
- log.Error(4, "%v", err)
+ log.Error(4, "GetRepositoryByID: %v", err)
continue
}
return nil, err
@@ -92,11 +91,28 @@ func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) {
}
repos[repo] = access.Mode
}
-
- // FIXME: should we generate an ordered list here? Random looks weird.
return repos, nil
}
+// GetAccessibleRepositories finds all repositories where a user has access but does not own.
+func (u *User) GetAccessibleRepositories() ([]*Repository, error) {
+ accesses := make([]*Access, 0, 10)
+ if err := x.Find(&accesses, &Access{UserID: u.Id}); err != nil {
+ return nil, err
+ }
+
+ if len(accesses) == 0 {
+ return []*Repository{}, nil
+ }
+
+ repoIDs := make([]int64, 0, len(accesses))
+ for _, access := range accesses {
+ repoIDs = append(repoIDs, access.RepoID)
+ }
+ repos := make([]*Repository, 0, len(repoIDs))
+ return repos, x.Where("owner_id != ?", u.Id).In("id", repoIDs).Desc("updated").Find(&repos)
+}
+
func maxAccessMode(modes ...AccessMode) AccessMode {
max := ACCESS_MODE_NONE
for _, mode := range modes {
diff --git a/models/action.go b/models/action.go
index e38cf593..8dd80074 100644
--- a/models/action.go
+++ b/models/action.go
@@ -14,6 +14,7 @@ import (
"time"
"unicode"
+ "github.com/Unknwon/com"
"github.com/go-xorm/xorm"
api "github.com/gogits/go-gogs-client"
@@ -136,6 +137,26 @@ func (a Action) GetIssueInfos() []string {
return strings.SplitN(a.Content, "|", 2)
}
+func (a Action) GetIssueTitle() string {
+ index := com.StrTo(a.GetIssueInfos()[0]).MustInt64()
+ issue, err := GetIssueByIndex(a.RepoID, index)
+ if err != nil {
+ log.Error(4, "GetIssueByIndex: %v", err)
+ return "500 when get issue"
+ }
+ return issue.Name
+}
+
+func (a Action) GetIssueContent() string {
+ index := com.StrTo(a.GetIssueInfos()[0]).MustInt64()
+ issue, err := GetIssueByIndex(a.RepoID, index)
+ if err != nil {
+ log.Error(4, "GetIssueByIndex: %v", err)
+ return "500 when get issue"
+ }
+ return issue.Content
+}
+
func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
if err = notifyWatchers(e, &Action{
ActUserID: u.Id,
@@ -147,7 +168,7 @@ func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
RepoName: repo.Name,
IsPrivate: repo.IsPrivate,
}); err != nil {
- return fmt.Errorf("notify watchers '%d/%s': %v", u.Id, repo.ID, err)
+ return fmt.Errorf("notify watchers '%d/%d': %v", u.Id, repo.ID, err)
}
log.Trace("action.newRepoAction: %s/%s", u.Name, repo.Name)
@@ -187,8 +208,48 @@ func issueIndexTrimRight(c rune) bool {
return !unicode.IsDigit(c)
}
+type PushCommit struct {
+ Sha1 string
+ Message string
+ AuthorEmail string
+ AuthorName string
+}
+
+type PushCommits struct {
+ Len int
+ Commits []*PushCommit
+ CompareUrl string
+
+ avatars map[string]string
+}
+
+func NewPushCommits() *PushCommits {
+ return &PushCommits{
+ avatars: make(map[string]string),
+ }
+}
+
+// AvatarLink tries to match user in database with e-mail
+// in order to show custom avatar, and falls back to general avatar link.
+func (push *PushCommits) AvatarLink(email string) string {
+ _, ok := push.avatars[email]
+ if !ok {
+ u, err := GetUserByEmail(email)
+ if err != nil {
+ push.avatars[email] = base.AvatarLink(email)
+ if !IsErrUserNotExist(err) {
+ log.Error(4, "GetUserByEmail: %v", err)
+ }
+ } else {
+ push.avatars[email] = u.AvatarLink()
+ }
+ }
+
+ return push.avatars[email]
+}
+
// updateIssuesCommit checks if issues are manipulated by commit message.
-func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string, commits []*base.PushCommit) error {
+func updateIssuesCommit(u *User, repo *Repository, repoUserName, repoName string, commits []*PushCommit) error {
// Commits are appended in the reverse order.
for i := len(commits) - 1; i >= 0; i-- {
c := commits[i]
@@ -322,7 +383,7 @@ func CommitRepoAction(
repoID int64,
repoUserName, repoName string,
refFullName string,
- commit *base.PushCommits,
+ commit *PushCommits,
oldCommitID string, newCommitID string) error {
u, err := GetUserByID(userID)
@@ -337,12 +398,18 @@ func CommitRepoAction(
return fmt.Errorf("GetOwner: %v", err)
}
+ // Change repository bare status and update last updated time.
+ repo.IsBare = false
+ if err = UpdateRepository(repo, false); err != nil {
+ return fmt.Errorf("UpdateRepository: %v", err)
+ }
+
isNewBranch := false
opType := COMMIT_REPO
// Check it's tag push or branch.
if strings.HasPrefix(refFullName, "refs/tags/") {
opType = PUSH_TAG
- commit = &base.PushCommits{}
+ commit = &PushCommits{}
} else {
// if not the first commit, set the compareUrl
if !strings.HasPrefix(oldCommitID, "0000000") {
@@ -351,12 +418,10 @@ func CommitRepoAction(
isNewBranch = true
}
- // Change repository bare status and update last updated time.
- repo.IsBare = false
- if err = UpdateRepository(repo, false); err != nil {
- return fmt.Errorf("UpdateRepository: %v", err)
+ // NOTE: limit to detect latest 100 commits.
+ if len(commit.Commits) > 100 {
+ commit.Commits = commit.Commits[len(commit.Commits)-100:]
}
-
if err = updateIssuesCommit(u, repo, repoUserName, repoName, commit.Commits); err != nil {
log.Error(4, "updateIssuesCommit: %v", err)
}
@@ -488,7 +553,7 @@ func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repos
IsPrivate: repo.IsPrivate,
Content: path.Join(oldOwner.LowerName, repo.LowerName),
}); err != nil {
- return fmt.Errorf("notify watchers '%d/%s': %v", actUser.Id, repo.ID, err)
+ return fmt.Errorf("notify watchers '%d/%d': %v", actUser.Id, repo.ID, err)
}
// Remove watch for organization.
diff --git a/models/error.go b/models/error.go
index f6973258..069346be 100644
--- a/models/error.go
+++ b/models/error.go
@@ -18,7 +18,7 @@ func IsErrNameReserved(err error) bool {
}
func (err ErrNameReserved) Error() string {
- return fmt.Sprintf("name is reserved: [name: %s]", err.Name)
+ return fmt.Sprintf("name is reserved [name: %s]", err.Name)
}
type ErrNamePatternNotAllowed struct {
@@ -31,7 +31,7 @@ func IsErrNamePatternNotAllowed(err error) bool {
}
func (err ErrNamePatternNotAllowed) Error() string {
- return fmt.Sprintf("name pattern is not allowed: [pattern: %s]", err.Pattern)
+ return fmt.Sprintf("name pattern is not allowed [pattern: %s]", err.Pattern)
}
// ____ ___
@@ -51,7 +51,7 @@ func IsErrUserAlreadyExist(err error) bool {
}
func (err ErrUserAlreadyExist) Error() string {
- return fmt.Sprintf("user already exists: [name: %s]", err.Name)
+ return fmt.Sprintf("user already exists [name: %s]", err.Name)
}
type ErrUserNotExist struct {
@@ -65,7 +65,7 @@ func IsErrUserNotExist(err error) bool {
}
func (err ErrUserNotExist) Error() string {
- return fmt.Sprintf("user does not exist: [uid: %d, name: %s]", err.UID, err.Name)
+ return fmt.Sprintf("user does not exist [uid: %d, name: %s]", err.UID, err.Name)
}
type ErrEmailAlreadyUsed struct {
@@ -78,7 +78,7 @@ func IsErrEmailAlreadyUsed(err error) bool {
}
func (err ErrEmailAlreadyUsed) Error() string {
- return fmt.Sprintf("e-mail has been used: [email: %s]", err.Email)
+ return fmt.Sprintf("e-mail has been used [email: %s]", err.Email)
}
type ErrUserOwnRepos struct {
@@ -91,7 +91,7 @@ func IsErrUserOwnRepos(err error) bool {
}
func (err ErrUserOwnRepos) Error() string {
- return fmt.Sprintf("user still has ownership of repositories: [uid: %d]", err.UID)
+ return fmt.Sprintf("user still has ownership of repositories [uid: %d]", err.UID)
}
type ErrUserHasOrgs struct {
@@ -104,7 +104,7 @@ func IsErrUserHasOrgs(err error) bool {
}
func (err ErrUserHasOrgs) Error() string {
- return fmt.Sprintf("user still has membership of organizations: [uid: %d]", err.UID)
+ return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
}
// __________ ___. .__ .__ ____ __.
@@ -114,6 +114,19 @@ func (err ErrUserHasOrgs) Error() string {
// |____| |____/|___ /____/__|\___ > |____|__ \___ > ____|
// \/ \/ \/ \/\/
+type ErrKeyUnableVerify struct {
+ Result string
+}
+
+func IsErrKeyUnableVerify(err error) bool {
+ _, ok := err.(ErrKeyUnableVerify)
+ return ok
+}
+
+func (err ErrKeyUnableVerify) Error() string {
+ return fmt.Sprintf("Unable to verify key content [result: %s]", err.Result)
+}
+
type ErrKeyNotExist struct {
ID int64
}
@@ -124,7 +137,7 @@ func IsErrKeyNotExist(err error) bool {
}
func (err ErrKeyNotExist) Error() string {
- return fmt.Sprintf("public key does not exist: [id: %d]", err.ID)
+ return fmt.Sprintf("public key does not exist [id: %d]", err.ID)
}
type ErrKeyAlreadyExist struct {
@@ -138,7 +151,7 @@ func IsErrKeyAlreadyExist(err error) bool {
}
func (err ErrKeyAlreadyExist) Error() string {
- return fmt.Sprintf("public key already exists: [owner_id: %d, content: %s]", err.OwnerID, err.Content)
+ return fmt.Sprintf("public key already exists [owner_id: %d, content: %s]", err.OwnerID, err.Content)
}
type ErrKeyNameAlreadyUsed struct {
@@ -152,7 +165,22 @@ func IsErrKeyNameAlreadyUsed(err error) bool {
}
func (err ErrKeyNameAlreadyUsed) Error() string {
- return fmt.Sprintf("public key already exists: [owner_id: %d, name: %s]", err.OwnerID, err.Name)
+ return fmt.Sprintf("public key already exists [owner_id: %d, name: %s]", err.OwnerID, err.Name)
+}
+
+type ErrDeployKeyNotExist struct {
+ ID int64
+ KeyID int64
+ RepoID int64
+}
+
+func IsErrDeployKeyNotExist(err error) bool {
+ _, ok := err.(ErrDeployKeyNotExist)
+ return ok
+}
+
+func (err ErrDeployKeyNotExist) Error() string {
+ return fmt.Sprintf("Deploy key does not exist [id: %d, key_id: %d, repo_id: %d]", err.ID, err.KeyID, err.RepoID)
}
type ErrDeployKeyAlreadyExist struct {
@@ -166,7 +194,7 @@ func IsErrDeployKeyAlreadyExist(err error) bool {
}
func (err ErrDeployKeyAlreadyExist) Error() string {
- return fmt.Sprintf("public key already exists: [key_id: %d, repo_id: %d]", err.KeyID, err.RepoID)
+ return fmt.Sprintf("public key already exists [key_id: %d, repo_id: %d]", err.KeyID, err.RepoID)
}
type ErrDeployKeyNameAlreadyUsed struct {
@@ -180,7 +208,7 @@ func IsErrDeployKeyNameAlreadyUsed(err error) bool {
}
func (err ErrDeployKeyNameAlreadyUsed) Error() string {
- return fmt.Sprintf("public key already exists: [repo_id: %d, name: %s]", err.RepoID, err.Name)
+ return fmt.Sprintf("public key already exists [repo_id: %d, name: %s]", err.RepoID, err.Name)
}
// _____ ___________ __
@@ -200,7 +228,7 @@ func IsErrAccessTokenNotExist(err error) bool {
}
func (err ErrAccessTokenNotExist) Error() string {
- return fmt.Sprintf("access token does not exist: [sha: %s]", err.SHA)
+ return fmt.Sprintf("access token does not exist [sha: %s]", err.SHA)
}
// ________ .__ __ .__
@@ -220,7 +248,7 @@ func IsErrLastOrgOwner(err error) bool {
}
func (err ErrLastOrgOwner) Error() string {
- return fmt.Sprintf("user is the last member of owner team: [uid: %d]", err.UID)
+ return fmt.Sprintf("user is the last member of owner team [uid: %d]", err.UID)
}
// __________ .__ __
@@ -259,6 +287,62 @@ func (err ErrRepoAlreadyExist) Error() string {
return fmt.Sprintf("repository already exists [uname: %s, name: %s]", err.Uname, err.Name)
}
+type ErrInvalidCloneAddr struct {
+ IsURLError bool
+ IsInvalidPath bool
+ IsPermissionDenied bool
+}
+
+func IsErrInvalidCloneAddr(err error) bool {
+ _, ok := err.(ErrInvalidCloneAddr)
+ return ok
+}
+
+func (err ErrInvalidCloneAddr) Error() string {
+ return fmt.Sprintf("invalid clone address [is_url_error: %v, is_invalid_path: %v, is_permission_denied: %v]",
+ err.IsURLError, err.IsInvalidPath, err.IsPermissionDenied)
+}
+
+type ErrUpdateTaskNotExist struct {
+ UUID string
+}
+
+func IsErrUpdateTaskNotExist(err error) bool {
+ _, ok := err.(ErrUpdateTaskNotExist)
+ return ok
+}
+
+func (err ErrUpdateTaskNotExist) Error() string {
+ return fmt.Sprintf("update task does not exist [uuid: %s]", err.UUID)
+}
+
+type ErrReleaseAlreadyExist struct {
+ TagName string
+}
+
+func IsErrReleaseAlreadyExist(err error) bool {
+ _, ok := err.(ErrReleaseAlreadyExist)
+ return ok
+}
+
+func (err ErrReleaseAlreadyExist) Error() string {
+ return fmt.Sprintf("Release tag already exist [tag_name: %s]", err.TagName)
+}
+
+type ErrReleaseNotExist struct {
+ ID int64
+ TagName string
+}
+
+func IsErrReleaseNotExist(err error) bool {
+ _, ok := err.(ErrReleaseNotExist)
+ return ok
+}
+
+func (err ErrReleaseNotExist) Error() string {
+ return fmt.Sprintf("Release tag does not exist [id: %d, tag_name: %s]", err.ID, err.TagName)
+}
+
// __ __ ___. .__ __
// / \ / \ ____\_ |__ | |__ ____ ____ | | __
// \ \/\/ // __ \| __ \| | \ / _ \ / _ \| |/ /
diff --git a/models/git_diff.go b/models/git_diff.go
index 2335e468..4b1ec09e 100644
--- a/models/git_diff.go
+++ b/models/git_diff.go
@@ -37,6 +37,7 @@ const (
DIFF_FILE_ADD = iota + 1
DIFF_FILE_CHANGE
DIFF_FILE_DEL
+ DIFF_FILE_RENAME
)
type DiffLine struct {
@@ -57,12 +58,14 @@ type DiffSection struct {
type DiffFile struct {
Name string
+ OldName string
Index int
Addition, Deletion int
Type int
IsCreated bool
IsDeleted bool
IsBin bool
+ IsRenamed bool
Sections []*DiffSection
}
@@ -94,7 +97,7 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
var i int
for scanner.Scan() {
line := scanner.Text()
- // fmt.Println(i, line)
+
if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") {
continue
}
@@ -158,17 +161,27 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
// Get new file.
if strings.HasPrefix(line, DIFF_HEAD) {
- beg := len(DIFF_HEAD)
- a := line[beg : (len(line)-beg)/2+beg]
+ middle := -1
+
+ // Note: In case file name is surrounded by double quotes (it happens only in git-shell).
+ // e.g. diff --git "a/xxx" "b/xxx"
+ hasQuote := line[len(DIFF_HEAD)] == '"'
+ if hasQuote {
+ middle = strings.Index(line, ` "b/`)
+ } else {
+ middle = strings.Index(line, " b/")
+ }
- // In case file name is surrounded by double quotes(it happens only in git-shell).
- if a[0] == '"' {
- a = a[1 : len(a)-1]
- a = strings.Replace(a, `\"`, `"`, -1)
+ beg := len(DIFF_HEAD)
+ a := line[beg+2 : middle]
+ b := line[middle+3:]
+ if hasQuote {
+ a = string(git.UnescapeChars([]byte(a[1 : len(a)-1])))
+ b = string(git.UnescapeChars([]byte(b[1 : len(b)-1])))
}
curFile = &DiffFile{
- Name: a[strings.Index(a, "/")+1:],
+ Name: a,
Index: len(diff.Files) + 1,
Type: DIFF_FILE_CHANGE,
Sections: make([]*DiffSection, 0, 10),
@@ -180,16 +193,17 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
switch {
case strings.HasPrefix(scanner.Text(), "new file"):
curFile.Type = DIFF_FILE_ADD
- curFile.IsDeleted = false
curFile.IsCreated = true
case strings.HasPrefix(scanner.Text(), "deleted"):
curFile.Type = DIFF_FILE_DEL
- curFile.IsCreated = false
curFile.IsDeleted = true
case strings.HasPrefix(scanner.Text(), "index"):
curFile.Type = DIFF_FILE_CHANGE
- curFile.IsCreated = false
- curFile.IsDeleted = false
+ case strings.HasPrefix(scanner.Text(), "similarity index 100%"):
+ curFile.Type = DIFF_FILE_RENAME
+ curFile.IsRenamed = true
+ curFile.OldName = curFile.Name
+ curFile.Name = b
}
if curFile.Type > 0 {
break
@@ -244,10 +258,10 @@ func GetDiffRange(repoPath, beforeCommitId string, afterCommitId string, maxline
cmd = exec.Command("git", "show", afterCommitId)
} else {
c, _ := commit.Parent(0)
- cmd = exec.Command("git", "diff", c.Id.String(), afterCommitId)
+ cmd = exec.Command("git", "diff", "-M", c.ID.String(), afterCommitId)
}
} else {
- cmd = exec.Command("git", "diff", beforeCommitId, afterCommitId)
+ cmd = exec.Command("git", "diff", "-M", beforeCommitId, afterCommitId)
}
cmd.Dir = repoPath
cmd.Stdout = wr
diff --git a/models/issue.go b/models/issue.go
index 077e945c..cee8c36a 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -718,32 +718,28 @@ func GetIssueStats(opts *IssueStatsOptions) *IssueStats {
if opts.AssigneeID > 0 {
baseCond += " AND assignee_id=" + com.ToStr(opts.AssigneeID)
}
- if opts.IsPull {
- baseCond += " AND issue.is_pull=1"
- } else {
- baseCond += " AND issue.is_pull=0"
- }
+ baseCond += " AND issue.is_pull=?"
switch opts.FilterMode {
case FM_ALL, FM_ASSIGN:
- results, _ := x.Query(queryStr+baseCond, false)
+ results, _ := x.Query(queryStr+baseCond, false, opts.IsPull)
stats.OpenCount = parseCountResult(results)
- results, _ = x.Query(queryStr+baseCond, true)
+ results, _ = x.Query(queryStr+baseCond, true, opts.IsPull)
stats.ClosedCount = parseCountResult(results)
case FM_CREATE:
baseCond += " AND poster_id=?"
- results, _ := x.Query(queryStr+baseCond, false, opts.UserID)
+ results, _ := x.Query(queryStr+baseCond, false, opts.IsPull, opts.UserID)
stats.OpenCount = parseCountResult(results)
- results, _ = x.Query(queryStr+baseCond, true, opts.UserID)
+ results, _ = x.Query(queryStr+baseCond, true, opts.IsPull, opts.UserID)
stats.ClosedCount = parseCountResult(results)
case FM_MENTION:
queryStr += " INNER JOIN `issue_user` ON `issue`.id=`issue_user`.issue_id"
baseCond += " AND `issue_user`.uid=? AND `issue_user`.is_mentioned=?"
- results, _ := x.Query(queryStr+baseCond, false, opts.UserID, true)
+ results, _ := x.Query(queryStr+baseCond, false, opts.IsPull, opts.UserID, true)
stats.OpenCount = parseCountResult(results)
- results, _ = x.Query(queryStr+baseCond, true, opts.UserID, true)
+ results, _ = x.Query(queryStr+baseCond, true, opts.IsPull, opts.UserID, true)
stats.ClosedCount = parseCountResult(results)
}
return stats
@@ -1375,8 +1371,8 @@ func ChangeMilestoneAssign(oldMid int64, issue *Issue) (err error) {
}
// DeleteMilestoneByID deletes a milestone by given ID.
-func DeleteMilestoneByID(mid int64) error {
- m, err := GetMilestoneByID(mid)
+func DeleteMilestoneByID(id int64) error {
+ m, err := GetMilestoneByID(id)
if err != nil {
if IsErrMilestoneNotExist(err) {
return nil
diff --git a/models/login.go b/models/login.go
index 79a262c5..011d946a 100644
--- a/models/login.go
+++ b/models/login.go
@@ -225,10 +225,9 @@ func DeleteSource(source *LoginSource) error {
// |_______ \/_______ /\____|__ /____|
// \/ \/ \/
-// Query if name/passwd can login against the LDAP directory pool
-// Create a local user if success
-// Return the same LoginUserPlain semantic
-// FIXME: https://github.com/gogits/gogs/issues/672
+// LoginUserLDAPSource queries if name/passwd can login against the LDAP directory pool,
+// and create a local user if success when enabled.
+// It returns the same LoginUserPlain semantic.
func LoginUserLDAPSource(u *User, name, passwd string, source *LoginSource, autoRegister bool) (*User, error) {
cfg := source.Cfg.(*LDAPConfig)
directBind := (source.Type == DLDAP)
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index c3f7a59b..0d17cf26 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -11,6 +11,7 @@ import (
"io/ioutil"
"os"
"path"
+ "path/filepath"
"strings"
"time"
@@ -66,6 +67,7 @@ var migrations = []Migration{
NewMigration("generate issue-label from issue", issueToIssueLabel), // V6 -> V7:v0.6.4
NewMigration("refactor attachment table", attachmentRefactor), // V7 -> V8:v0.6.4
NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16
+ NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20
}
// Migrate database to current version
@@ -454,7 +456,7 @@ func trimCommitActionAppUrlPrefix(x *xorm.Engine) error {
pushCommits = new(PushCommits)
if err = json.Unmarshal(action["content"], pushCommits); err != nil {
- return fmt.Errorf("unmarshal action content[%s]: %v", actID, err)
+ return fmt.Errorf("unmarshal action content[%d]: %v", actID, err)
}
infos := strings.Split(pushCommits.CompareUrl, "/")
@@ -465,7 +467,7 @@ func trimCommitActionAppUrlPrefix(x *xorm.Engine) error {
p, err := json.Marshal(pushCommits)
if err != nil {
- return fmt.Errorf("marshal action content[%s]: %v", actID, err)
+ return fmt.Errorf("marshal action content[%d]: %v", actID, err)
}
if _, err = sess.Id(actID).Update(&Action{
@@ -653,3 +655,50 @@ func renamePullRequestFields(x *xorm.Engine) (err error) {
return sess.Commit()
}
+
+func cleanUpMigrateRepoInfo(x *xorm.Engine) (err error) {
+ type (
+ User struct {
+ ID int64 `xorm:"pk autoincr"`
+ LowerName string
+ }
+ Repository struct {
+ ID int64 `xorm:"pk autoincr"`
+ OwnerID int64
+ LowerName string
+ }
+ )
+
+ repos := make([]*Repository, 0, 25)
+ if err = x.Where("is_mirror=?", false).Find(&repos); err != nil {
+ return fmt.Errorf("select all non-mirror repositories: %v", err)
+ }
+ var user *User
+ for _, repo := range repos {
+ user = &User{ID: repo.OwnerID}
+ has, err := x.Get(user)
+ if err != nil {
+ return fmt.Errorf("get owner of repository[%d - %d]: %v", repo.ID, repo.OwnerID, err)
+ } else if !has {
+ continue
+ }
+
+ configPath := filepath.Join(setting.RepoRootPath, user.LowerName, repo.LowerName+".git/config")
+
+ // In case repository file is somehow missing.
+ if !com.IsFile(configPath) {
+ continue
+ }
+
+ cfg, err := ini.Load(configPath)
+ if err != nil {
+ return fmt.Errorf("open config file: %v", err)
+ }
+ cfg.DeleteSection("remote \"origin\"")
+ if err = cfg.SaveToIndent(configPath, "\t"); err != nil {
+ return fmt.Errorf("save config file: %v", err)
+ }
+ }
+
+ return nil
+}
diff --git a/models/models.go b/models/models.go
index 802bc942..2249fee4 100644
--- a/models/models.go
+++ b/models/models.go
@@ -90,7 +90,7 @@ func init() {
new(Team), new(OrgUser), new(TeamUser), new(TeamRepo),
new(Notice), new(EmailAddress))
- gonicNames := []string{"UID", "SSL"}
+ gonicNames := []string{"SSL"}
for _, name := range gonicNames {
core.LintGonicMapper[name] = true
}
diff --git a/models/publickey.go b/models/publickey.go
index 6c0ffc0c..b5646a55 100644
--- a/models/publickey.go
+++ b/models/publickey.go
@@ -13,7 +13,6 @@ import (
"io"
"io/ioutil"
"os"
- "os/exec"
"path"
"path/filepath"
"strings"
@@ -33,25 +32,8 @@ const (
_TPL_PUBLICK_KEY = `command="%s serv key-%d --config='%s'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` + "\n"
)
-var (
- ErrKeyUnableVerify = errors.New("Unable to verify public key")
-)
-
var sshOpLocker = sync.Mutex{}
-
-var (
- SSHPath string // SSH directory.
- appPath string // Execution(binary) path.
-)
-
-// exePath returns the executable path.
-func exePath() (string, error) {
- file, err := exec.LookPath(os.Args[0])
- if err != nil {
- return "", err
- }
- return filepath.Abs(file)
-}
+var SSHPath string // SSH directory.
// homeDir returns the home directory of current user.
func homeDir() string {
@@ -63,16 +45,9 @@ func homeDir() string {
}
func init() {
- var err error
-
- if appPath, err = exePath(); err != nil {
- log.Fatal(4, "fail to get app path: %v\n", err)
- }
- appPath = strings.Replace(appPath, "\\", "/", -1)
-
// Determine and create .ssh path.
SSHPath = filepath.Join(homeDir(), ".ssh")
- if err = os.MkdirAll(SSHPath, 0700); err != nil {
+ if err := os.MkdirAll(SSHPath, 0700); err != nil {
log.Fatal(4, "fail to create '%s': %v", SSHPath, err)
}
}
@@ -114,17 +89,7 @@ func (k *PublicKey) OmitEmail() string {
// GetAuthorizedString generates and returns formatted public key string for authorized_keys file.
func (key *PublicKey) GetAuthorizedString() string {
- return fmt.Sprintf(_TPL_PUBLICK_KEY, appPath, key.ID, setting.CustomConf, key.Content)
-}
-
-var minimumKeySizes = map[string]int{
- "(ED25519)": 256,
- "(ECDSA)": 256,
- "(NTRU)": 1087,
- "(MCE)": 1702,
- "(McE)": 1702,
- "(RSA)": 1024,
- "(DSA)": 1024,
+ return fmt.Sprintf(_TPL_PUBLICK_KEY, setting.AppPath, key.ID, setting.CustomConf, key.Content)
}
func extractTypeFromBase64Key(key string) (string, error) {
@@ -228,9 +193,9 @@ func CheckPublicKeyString(content string) (_ string, err error) {
tmpFile.Close()
// Check if ssh-keygen recognizes its contents.
- stdout, stderr, err := process.Exec("CheckPublicKeyString", "ssh-keygen", "-l", "-f", tmpPath)
+ stdout, stderr, err := process.Exec("CheckPublicKeyString", "ssh-keygen", "-lf", tmpPath)
if err != nil {
- return "", errors.New("ssh-keygen -l -f: " + stderr)
+ return "", errors.New("ssh-keygen -lf: " + stderr)
} else if len(stdout) < 2 {
return "", errors.New("ssh-keygen returned not enough output to evaluate the key: " + stdout)
}
@@ -242,7 +207,7 @@ func CheckPublicKeyString(content string) (_ string, err error) {
sshKeygenOutput := strings.Split(stdout, " ")
if len(sshKeygenOutput) < 4 {
- return content, ErrKeyUnableVerify
+ return content, ErrKeyUnableVerify{stdout}
}
// Check if key type and key size match.
@@ -251,9 +216,10 @@ func CheckPublicKeyString(content string) (_ string, err error) {
if keySize == 0 {
return "", errors.New("cannot get key size of the given key")
}
- keyType := strings.TrimSpace(sshKeygenOutput[len(sshKeygenOutput)-1])
- if minimumKeySize := minimumKeySizes[keyType]; minimumKeySize == 0 {
- return "", errors.New("sorry, unrecognized public key type")
+
+ keyType := strings.Trim(sshKeygenOutput[len(sshKeygenOutput)-1], " ()\n")
+ if minimumKeySize := setting.Service.MinimumKeySizes[keyType]; minimumKeySize == 0 {
+ return "", fmt.Errorf("unrecognized public key type: %s", keyType)
} else if keySize < minimumKeySize {
return "", fmt.Errorf("the minimum accepted size of a public key %s is %d", keyType, minimumKeySize)
}
@@ -321,9 +287,9 @@ func addKey(e Engine, key *PublicKey) (err error) {
if err = ioutil.WriteFile(tmpPath, []byte(key.Content), 0644); err != nil {
return err
}
- stdout, stderr, err := process.Exec("AddPublicKey", "ssh-keygen", "-l", "-f", tmpPath)
+ stdout, stderr, err := process.Exec("AddPublicKey", "ssh-keygen", "-lf", tmpPath)
if err != nil {
- return errors.New("ssh-keygen -l -f: " + stderr)
+ return errors.New("ssh-keygen -lf: " + stderr)
} else if len(stdout) < 2 {
return errors.New("not enough output for calculating fingerprint: " + stdout)
}
@@ -382,6 +348,19 @@ func GetPublicKeyByID(keyID int64) (*PublicKey, error) {
return key, nil
}
+// SearchPublicKeyByContent searches content as prefix (leak e-mail part)
+// and returns public key found.
+func SearchPublicKeyByContent(content string) (*PublicKey, error) {
+ key := new(PublicKey)
+ has, err := x.Where("content like ?", content+"%").Get(key)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrKeyNotExist{}
+ }
+ return key, nil
+}
+
// ListPublicKeys returns a list of public keys belongs to given user.
func ListPublicKeys(uid int64) ([]*PublicKey, error) {
keys := make([]*PublicKey, 0, 5)
@@ -540,6 +519,7 @@ type DeployKey struct {
RepoID int64 `xorm:"UNIQUE(s) INDEX"`
Name string
Fingerprint string
+ Content string `xorm:"-"`
Created time.Time `xorm:"CREATED"`
Updated time.Time // Note: Updated must below Created for AfterSet.
HasRecentActivity bool `xorm:"-"`
@@ -554,6 +534,16 @@ func (k *DeployKey) AfterSet(colName string, _ xorm.Cell) {
}
}
+// GetContent gets associated public key content.
+func (k *DeployKey) GetContent() error {
+ pkey, err := GetPublicKeyByID(k.KeyID)
+ if err != nil {
+ return err
+ }
+ k.Content = pkey.Content
+ return nil
+}
+
func checkDeployKey(e Engine, keyID, repoID int64, name string) error {
// Note: We want error detail, not just true or false here.
has, err := e.Where("key_id=? AND repo_id=?", keyID, repoID).Get(new(DeployKey))
@@ -574,18 +564,19 @@ func checkDeployKey(e Engine, keyID, repoID int64, name string) error {
}
// addDeployKey adds new key-repo relation.
-func addDeployKey(e *xorm.Session, keyID, repoID int64, name, fingerprint string) (err error) {
- if err = checkDeployKey(e, keyID, repoID, name); err != nil {
- return err
+func addDeployKey(e *xorm.Session, keyID, repoID int64, name, fingerprint string) (*DeployKey, error) {
+ if err := checkDeployKey(e, keyID, repoID, name); err != nil {
+ return nil, err
}
- _, err = e.Insert(&DeployKey{
+ key := &DeployKey{
KeyID: keyID,
RepoID: repoID,
Name: name,
Fingerprint: fingerprint,
- })
- return err
+ }
+ _, err := e.Insert(key)
+ return key, err
}
// HasDeployKey returns true if public key is a deploy key of given repository.
@@ -595,39 +586,52 @@ func HasDeployKey(keyID, repoID int64) bool {
}
// AddDeployKey add new deploy key to database and authorized_keys file.
-func AddDeployKey(repoID int64, name, content string) (err error) {
- if err = checkKeyContent(content); err != nil {
- return err
+func AddDeployKey(repoID int64, name, content string) (*DeployKey, error) {
+ if err := checkKeyContent(content); err != nil {
+ return nil, err
}
- key := &PublicKey{
+ pkey := &PublicKey{
Content: content,
Mode: ACCESS_MODE_READ,
Type: KEY_TYPE_DEPLOY,
}
- has, err := x.Get(key)
+ has, err := x.Get(pkey)
if err != nil {
- return err
+ return nil, err
}
sess := x.NewSession()
defer sessionRelease(sess)
if err = sess.Begin(); err != nil {
- return err
+ return nil, err
}
// First time use this deploy key.
if !has {
- if err = addKey(sess, key); err != nil {
- return nil
+ if err = addKey(sess, pkey); err != nil {
+ return nil, fmt.Errorf("addKey: %v", err)
}
}
- if err = addDeployKey(sess, key.ID, repoID, name, key.Fingerprint); err != nil {
- return err
+ key, err := addDeployKey(sess, pkey.ID, repoID, name, pkey.Fingerprint)
+ if err != nil {
+ return nil, fmt.Errorf("addDeployKey: %v", err)
}
- return sess.Commit()
+ return key, sess.Commit()
+}
+
+// GetDeployKeyByID returns deploy key by given ID.
+func GetDeployKeyByID(id int64) (*DeployKey, error) {
+ key := new(DeployKey)
+ has, err := x.Id(id).Get(key)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrDeployKeyNotExist{id, 0, 0}
+ }
+ return key, nil
}
// GetDeployKeyByRepo returns deploy key by given public key ID and repository ID.
@@ -636,8 +640,13 @@ func GetDeployKeyByRepo(keyID, repoID int64) (*DeployKey, error) {
KeyID: keyID,
RepoID: repoID,
}
- _, err := x.Get(key)
- return key, err
+ has, err := x.Get(key)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrDeployKeyNotExist{0, keyID, repoID}
+ }
+ return key, nil
}
// UpdateDeployKey updates deploy key information.
diff --git a/models/pull.go b/models/pull.go
index 0300c083..dfd80635 100644
--- a/models/pull.go
+++ b/models/pull.go
@@ -166,43 +166,49 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
var stderr string
if _, stderr, err = process.ExecTimeout(5*time.Minute,
- fmt.Sprintf("PullRequest.Merge(git clone): %s", tmpBasePath),
+ fmt.Sprintf("PullRequest.Merge (git clone): %s", tmpBasePath),
"git", "clone", baseGitRepo.Path, tmpBasePath); err != nil {
return fmt.Errorf("git clone: %s", stderr)
}
// Check out base branch.
if _, stderr, err = process.ExecDir(-1, tmpBasePath,
- fmt.Sprintf("PullRequest.Merge(git checkout): %s", tmpBasePath),
+ fmt.Sprintf("PullRequest.Merge (git checkout): %s", tmpBasePath),
"git", "checkout", pr.BaseBranch); err != nil {
return fmt.Errorf("git checkout: %s", stderr)
}
// Add head repo remote.
if _, stderr, err = process.ExecDir(-1, tmpBasePath,
- fmt.Sprintf("PullRequest.Merge(git remote add): %s", tmpBasePath),
+ fmt.Sprintf("PullRequest.Merge (git remote add): %s", tmpBasePath),
"git", "remote", "add", "head_repo", headRepoPath); err != nil {
- return fmt.Errorf("git remote add[%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
+ return fmt.Errorf("git remote add [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
}
// Merge commits.
if _, stderr, err = process.ExecDir(-1, tmpBasePath,
- fmt.Sprintf("PullRequest.Merge(git fetch): %s", tmpBasePath),
+ fmt.Sprintf("PullRequest.Merge (git fetch): %s", tmpBasePath),
"git", "fetch", "head_repo"); err != nil {
- return fmt.Errorf("git fetch[%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
+ return fmt.Errorf("git fetch [%s -> %s]: %s", headRepoPath, tmpBasePath, stderr)
}
if _, stderr, err = process.ExecDir(-1, tmpBasePath,
- fmt.Sprintf("PullRequest.Merge(git merge): %s", tmpBasePath),
- "git", "merge", "--no-ff", "-m",
- fmt.Sprintf("Merge branch '%s' of %s/%s into %s", pr.HeadBranch, pr.HeadUserName, pr.HeadRepo.Name, pr.BaseBranch),
- "head_repo/"+pr.HeadBranch); err != nil {
- return fmt.Errorf("git merge[%s]: %s", tmpBasePath, stderr)
+ fmt.Sprintf("PullRequest.Merge (git merge --no-ff --no-commit): %s", tmpBasePath),
+ "git", "merge", "--no-ff", "--no-commit", "head_repo/"+pr.HeadBranch); err != nil {
+ return fmt.Errorf("git merge --no-ff --no-commit [%s]: %v - %s", tmpBasePath, err, stderr)
+ }
+
+ sig := doer.NewGitSig()
+ if _, stderr, err = process.ExecDir(-1, tmpBasePath,
+ fmt.Sprintf("PullRequest.Merge (git merge): %s", tmpBasePath),
+ "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
+ "-m", fmt.Sprintf("Merge branch '%s' of %s/%s into %s", pr.HeadBranch, pr.HeadUserName, pr.HeadRepo.Name, pr.BaseBranch)); err != nil {
+ return fmt.Errorf("git commit [%s]: %v - %s", tmpBasePath, err, stderr)
}
// Push back to upstream.
if _, stderr, err = process.ExecDir(-1, tmpBasePath,
- fmt.Sprintf("PullRequest.Merge(git push): %s", tmpBasePath),
+ fmt.Sprintf("PullRequest.Merge (git push): %s", tmpBasePath),
"git", "push", baseGitRepo.Path, pr.BaseBranch); err != nil {
return fmt.Errorf("git push: %s", stderr)
}
@@ -218,6 +224,7 @@ var patchConflicts = []string{
}
// testPatch checks if patch can be merged to base repository without conflit.
+// FIXME: make a mechanism to clean up stable local copies.
func (pr *PullRequest) testPatch() (err error) {
if pr.BaseRepo == nil {
pr.BaseRepo, err = GetRepositoryByID(pr.BaseRepoID)
@@ -243,14 +250,23 @@ func (pr *PullRequest) testPatch() (err error) {
return fmt.Errorf("UpdateLocalCopy: %v", err)
}
- pr.Status = PULL_REQUEST_STATUS_CHECKING
+ // Checkout base branch.
_, stderr, err := process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
+ fmt.Sprintf("PullRequest.Merge(git checkout): %s", pr.BaseRepo.ID),
+ "git", "checkout", pr.BaseBranch)
+ if err != nil {
+ return fmt.Errorf("git checkout: %s", stderr)
+ }
+
+ pr.Status = PULL_REQUEST_STATUS_CHECKING
+ _, stderr, err = process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
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)
+ fmt.Println(stderr)
pr.Status = PULL_REQUEST_STATUS_CONFLICT
return nil
}
@@ -385,16 +401,18 @@ func (pr *PullRequest) UpdateCols(cols ...string) error {
var PullRequestQueue = NewUniqueQueue(setting.Repository.PullRequestQueueLength)
// UpdatePatch generates and saves a new patch.
-func (pr *PullRequest) UpdatePatch() error {
- if err := pr.GetHeadRepo(); err != nil {
+func (pr *PullRequest) UpdatePatch() (err error) {
+ if err = pr.GetHeadRepo(); err != nil {
return fmt.Errorf("GetHeadRepo: %v", err)
} else if pr.HeadRepo == nil {
log.Trace("PullRequest[%d].UpdatePatch: ignored cruppted data", pr.ID)
return nil
}
- if err := pr.GetBaseRepo(); err != nil {
+ if err = pr.GetBaseRepo(); err != nil {
return fmt.Errorf("GetBaseRepo: %v", err)
+ } else if err = pr.BaseRepo.GetOwner(); err != nil {
+ return fmt.Errorf("GetOwner: %v", err)
}
headRepoPath, err := pr.HeadRepo.RepoPath()
@@ -407,6 +425,22 @@ func (pr *PullRequest) UpdatePatch() error {
return fmt.Errorf("OpenRepository: %v", err)
}
+ // Add a temporary remote.
+ tmpRemote := com.ToStr(time.Now().UnixNano())
+ if err = headGitRepo.AddRemote(tmpRemote, RepoPath(pr.BaseRepo.Owner.Name, pr.BaseRepo.Name)); err != nil {
+ return fmt.Errorf("AddRemote: %v", err)
+ }
+ defer func() {
+ headGitRepo.RemoveRemote(tmpRemote)
+ }()
+ remoteBranch := "remotes/" + tmpRemote + "/" + pr.BaseBranch
+ pr.MergeBase, err = headGitRepo.GetMergeBase(remoteBranch, pr.HeadBranch)
+ if err != nil {
+ return fmt.Errorf("GetMergeBase: %v", err)
+ } else if err = pr.Update(); err != nil {
+ return fmt.Errorf("Update: %v", err)
+ }
+
patch, err := headGitRepo.GetPatch(pr.MergeBase, pr.HeadBranch)
if err != nil {
return fmt.Errorf("GetPatch: %v", err)
diff --git a/models/release.go b/models/release.go
index 027491d9..ef1d640d 100644
--- a/models/release.go
+++ b/models/release.go
@@ -5,7 +5,7 @@
package models
import (
- "errors"
+ "fmt"
"sort"
"strings"
"time"
@@ -13,18 +13,14 @@ import (
"github.com/go-xorm/xorm"
"github.com/gogits/gogs/modules/git"
-)
-
-var (
- ErrReleaseAlreadyExist = errors.New("Release already exist")
- ErrReleaseNotExist = errors.New("Release does not exist")
+ "github.com/gogits/gogs/modules/process"
)
// Release represents a release of repository.
type Release struct {
- Id int64
- RepoId int64
- PublisherId int64
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64
+ PublisherID int64
Publisher *User `xorm:"-"`
TagName string
LowerTagName string
@@ -47,12 +43,12 @@ func (r *Release) AfterSet(colName string, _ xorm.Cell) {
}
// IsReleaseExist returns true if release with given tag name already exists.
-func IsReleaseExist(repoId int64, tagName string) (bool, error) {
+func IsReleaseExist(repoID int64, tagName string) (bool, error) {
if len(tagName) == 0 {
return false, nil
}
- return x.Get(&Release{RepoId: repoId, LowerTagName: strings.ToLower(tagName)})
+ return x.Get(&Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)})
}
func createTag(gitRepo *git.Repository, rel *Release) error {
@@ -64,7 +60,7 @@ func createTag(gitRepo *git.Repository, rel *Release) error {
return err
}
- if err = gitRepo.CreateTag(rel.TagName, commit.Id.String()); err != nil {
+ if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
return err
}
} else {
@@ -84,11 +80,11 @@ func createTag(gitRepo *git.Repository, rel *Release) error {
// CreateRelease creates a new release of repository.
func CreateRelease(gitRepo *git.Repository, rel *Release) error {
- isExist, err := IsReleaseExist(rel.RepoId, rel.TagName)
+ isExist, err := IsReleaseExist(rel.RepoID, rel.TagName)
if err != nil {
return err
} else if isExist {
- return ErrReleaseAlreadyExist
+ return ErrReleaseAlreadyExist{rel.TagName}
}
if err = createTag(gitRepo, rel); err != nil {
@@ -100,22 +96,35 @@ func CreateRelease(gitRepo *git.Repository, rel *Release) error {
}
// GetRelease returns release by given ID.
-func GetRelease(repoId int64, tagName string) (*Release, error) {
- isExist, err := IsReleaseExist(repoId, tagName)
+func GetRelease(repoID int64, tagName string) (*Release, error) {
+ isExist, err := IsReleaseExist(repoID, tagName)
if err != nil {
return nil, err
} else if !isExist {
- return nil, ErrReleaseNotExist
+ return nil, ErrReleaseNotExist{0, tagName}
}
- rel := &Release{RepoId: repoId, LowerTagName: strings.ToLower(tagName)}
+ rel := &Release{RepoID: repoID, LowerTagName: strings.ToLower(tagName)}
_, err = x.Get(rel)
return rel, err
}
-// GetReleasesByRepoId returns a list of releases of repository.
-func GetReleasesByRepoId(repoId int64) (rels []*Release, err error) {
- err = x.Desc("created").Find(&rels, Release{RepoId: repoId})
+// GetReleaseByID returns release with given ID.
+func GetReleaseByID(id int64) (*Release, error) {
+ rel := new(Release)
+ has, err := x.Id(id).Get(rel)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrReleaseNotExist{id, ""}
+ }
+
+ return rel, nil
+}
+
+// GetReleasesByRepoID returns a list of releases of repository.
+func GetReleasesByRepoID(repoID int64) (rels []*Release, err error) {
+ err = x.Desc("created").Find(&rels, Release{RepoID: repoID})
return rels, err
}
@@ -150,6 +159,36 @@ func UpdateRelease(gitRepo *git.Repository, rel *Release) (err error) {
if err = createTag(gitRepo, rel); err != nil {
return err
}
- _, err = x.Id(rel.Id).AllCols().Update(rel)
+ _, err = x.Id(rel.ID).AllCols().Update(rel)
return err
}
+
+// DeleteReleaseByID deletes a release and corresponding Git tag by given ID.
+func DeleteReleaseByID(id int64) error {
+ rel, err := GetReleaseByID(id)
+ if err != nil {
+ return fmt.Errorf("GetReleaseByID: %v", err)
+ }
+
+ repo, err := GetRepositoryByID(rel.RepoID)
+ if err != nil {
+ return fmt.Errorf("GetRepositoryByID: %v", err)
+ }
+
+ repoPath, err := repo.RepoPath()
+ if err != nil {
+ return fmt.Errorf("RepoPath: %v", err)
+ }
+
+ _, stderr, err := process.ExecDir(-1, 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 {
+ return fmt.Errorf("Delete: %v", err)
+ }
+
+ return nil
+}
diff --git a/models/repo.go b/models/repo.go
index 197415c6..b628e752 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -17,12 +17,14 @@ import (
"regexp"
"sort"
"strings"
+ "sync"
"time"
"unicode/utf8"
"github.com/Unknwon/cae/zip"
"github.com/Unknwon/com"
"github.com/go-xorm/xorm"
+ "gopkg.in/ini.v1"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/bindata"
@@ -48,7 +50,7 @@ var (
Gitignores, Licenses, Readmes []string
// Maximum items per page in forks, watchers and stars of a repo
- ItemsPerPage = 54
+ ItemsPerPage = 40
)
func LoadRepoConfig() {
@@ -319,7 +321,7 @@ func (repo *Repository) UpdateLocalCopy() error {
}
} else {
_, stderr, err := process.ExecDir(-1, localPath,
- fmt.Sprintf("UpdateLocalCopy(git pull): %s", repoPath), "git", "pull")
+ fmt.Sprintf("UpdateLocalCopy(git pull --all): %s", repoPath), "git", "pull", "--all")
if err != nil {
return fmt.Errorf("git pull: %v - %s", err, stderr)
}
@@ -379,11 +381,11 @@ func (repo *Repository) CloneLink() (cl CloneLink, err error) {
}
if setting.SSHPort != 22 {
- cl.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.SSHDomain, setting.SSHPort, repo.Owner.LowerName, repo.LowerName)
+ cl.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.SSHDomain, setting.SSHPort, repo.Owner.Name, repo.Name)
} else {
- cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.SSHDomain, repo.Owner.LowerName, repo.LowerName)
+ cl.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.SSHDomain, repo.Owner.Name, repo.Name)
}
- cl.HTTPS = fmt.Sprintf("%s%s/%s.git", setting.AppUrl, repo.Owner.LowerName, repo.LowerName)
+ cl.HTTPS = fmt.Sprintf("%s%s/%s.git", setting.AppUrl, repo.Owner.Name, repo.Name)
return cl, nil
}
@@ -537,6 +539,17 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
return repo, fmt.Errorf("create update hook: %v", err)
}
+ // Clean up mirror info which prevents "push --all".
+ configPath := filepath.Join(repoPath, "/config")
+ cfg, err := ini.Load(configPath)
+ if err != nil {
+ return repo, fmt.Errorf("open config file: %v", err)
+ }
+ cfg.DeleteSection("remote \"origin\"")
+ if err = cfg.SaveToIndent(configPath, "\t"); err != nil {
+ return repo, fmt.Errorf("save config file: %v", err)
+ }
+
// Check if repository is empty.
_, stderr, err = com.ExecCmdDir(repoPath, "git", "log", "-1")
if err != nil {
@@ -563,20 +576,20 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
func initRepoCommit(tmpPath string, sig *git.Signature) (err error) {
var stderr string
if _, stderr, err = process.ExecDir(-1,
- tmpPath, fmt.Sprintf("initRepoCommit(git add): %s", tmpPath),
+ tmpPath, fmt.Sprintf("initRepoCommit (git add): %s", tmpPath),
"git", "add", "--all"); err != nil {
return fmt.Errorf("git add: %s", stderr)
}
if _, stderr, err = process.ExecDir(-1,
- tmpPath, fmt.Sprintf("initRepoCommit(git commit): %s", tmpPath),
+ tmpPath, fmt.Sprintf("initRepoCommit (git commit): %s", tmpPath),
"git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email),
"-m", "initial commit"); err != nil {
return fmt.Errorf("git commit: %s", stderr)
}
if _, stderr, err = process.ExecDir(-1,
- tmpPath, fmt.Sprintf("initRepoCommit(git push): %s", tmpPath),
+ tmpPath, fmt.Sprintf("initRepoCommit (git push): %s", tmpPath),
"git", "push", "origin", "master"); err != nil {
return fmt.Errorf("git push: %s", stderr)
}
@@ -587,7 +600,7 @@ func createUpdateHook(repoPath string) error {
hookPath := path.Join(repoPath, "hooks/update")
os.MkdirAll(path.Dir(hookPath), os.ModePerm)
return ioutil.WriteFile(hookPath,
- []byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+appPath+"\"", setting.CustomConf)), 0777)
+ []byte(fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+setting.AppPath+"\"", setting.CustomConf)), 0777)
}
type CreateRepoOptions struct {
@@ -687,7 +700,7 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts C
// Init bare new repository.
os.MkdirAll(repoPath, os.ModePerm)
_, stderr, err := process.ExecDir(-1, repoPath,
- fmt.Sprintf("initRepository(git init --bare): %s", repoPath), "git", "init", "--bare")
+ fmt.Sprintf("initRepository (git init --bare): %s", repoPath), "git", "init", "--bare")
if err != nil {
return fmt.Errorf("git init --bare: %v - %s", err, stderr)
}
@@ -898,9 +911,9 @@ func TransferOwnership(u *User, newOwnerName string, repo *Repository) error {
}
// Remove redundant collaborators.
- collaborators, err := repo.GetCollaborators()
+ collaborators, err := repo.getCollaborators(sess)
if err != nil {
- return fmt.Errorf("GetCollaborators: %v", err)
+ return fmt.Errorf("getCollaborators: %v", err)
}
// Dummy object.
@@ -936,9 +949,9 @@ func TransferOwnership(u *User, newOwnerName string, repo *Repository) error {
}
if newOwner.IsOrganization() {
- t, err := newOwner.GetOwnerTeam()
+ t, err := newOwner.getOwnerTeam(sess)
if err != nil {
- return fmt.Errorf("GetOwnerTeam: %v", err)
+ return fmt.Errorf("getOwnerTeam: %v", err)
} else if err = t.addRepository(sess, repo); err != nil {
return fmt.Errorf("add to owner team: %v", err)
}
@@ -1104,7 +1117,7 @@ func DeleteRepository(uid, repoID int64) error {
return err
} 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 {
return err
@@ -1304,7 +1317,7 @@ func DeleteRepositoryArchives() error {
repo := bean.(*Repository)
repoPath, err := repo.RepoPath()
if err != nil {
- if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepositoryArchives[%d]: %v", repo.ID, err)); err2 != nil {
+ if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepositoryArchives.RepoPath [%d]: %v", repo.ID, err)); err2 != nil {
log.Error(4, "CreateRepositoryNotice: %v", err2)
}
return nil
@@ -1313,32 +1326,110 @@ func DeleteRepositoryArchives() error {
})
}
+// DeleteMissingRepositories deletes all repository records that lost Git files.
+func DeleteMissingRepositories() error {
+ repos := make([]*Repository, 0, 5)
+ if err := x.Where("id > 0").Iterate(new(Repository),
+ func(idx int, bean interface{}) error {
+ repo := bean.(*Repository)
+ repoPath, err := repo.RepoPath()
+ if err != nil {
+ if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepositoryArchives.RepoPath [%d]: %v", repo.ID, err)); err2 != nil {
+ log.Error(4, "CreateRepositoryNotice: %v", err2)
+ }
+ return nil
+ }
+
+ if !com.IsDir(repoPath) {
+ repos = append(repos, repo)
+ }
+ return nil
+ }); err != nil {
+ if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteMissingRepositories: %v", err)); err2 != nil {
+ log.Error(4, "CreateRepositoryNotice: %v", err2)
+ }
+ return nil
+ }
+
+ if len(repos) == 0 {
+ return nil
+ }
+
+ for _, repo := range repos {
+ 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 nil
+}
+
// RewriteRepositoryUpdateHook rewrites all repositories' update hook.
func RewriteRepositoryUpdateHook() error {
return x.Where("id > 0").Iterate(new(Repository),
func(idx int, bean interface{}) error {
repo := bean.(*Repository)
- if err := repo.GetOwner(); err != nil {
- return err
+ repoPath, err := repo.RepoPath()
+ if err != nil {
+ if err2 := CreateRepositoryNotice(fmt.Sprintf("RewriteRepositoryUpdateHook[%d]: %v", repo.ID, err)); err2 != nil {
+ log.Error(4, "CreateRepositoryNotice: %v", err2)
+ }
+ return nil
}
- return createUpdateHook(RepoPath(repo.Owner.Name, repo.Name))
+ return createUpdateHook(repoPath)
})
}
-var (
- // Prevent duplicate running tasks.
- isMirrorUpdating = false
- isGitFscking = false
- isCheckingRepos = false
+// statusPool represents a pool of status with true/false.
+type statusPool struct {
+ lock sync.RWMutex
+ pool map[string]bool
+}
+
+// Start sets value of given name to true in the pool.
+func (p *statusPool) Start(name string) {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ p.pool[name] = true
+}
+
+// Stop sets value of given name to false in the pool.
+func (p *statusPool) Stop(name string) {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ p.pool[name] = false
+}
+
+// IsRunning checks if value of given name is set to true in the pool.
+func (p *statusPool) IsRunning(name string) bool {
+ p.lock.RLock()
+ defer p.lock.RUnlock()
+
+ return p.pool[name]
+}
+
+// Prevent duplicate running tasks.
+var taskStatusPool = &statusPool{
+ pool: make(map[string]bool),
+}
+
+const (
+ _MIRROR_UPDATE = "mirror_update"
+ _GIT_FSCK = "git_fsck"
+ _CHECK_REPOs = "check_repos"
)
// MirrorUpdate checks and updates mirror repositories.
func MirrorUpdate() {
- if isMirrorUpdating {
+ if taskStatusPool.IsRunning(_MIRROR_UPDATE) {
return
}
- isMirrorUpdating = true
- defer func() { isMirrorUpdating = false }()
+ taskStatusPool.Start(_MIRROR_UPDATE)
+ defer taskStatusPool.Stop(_MIRROR_UPDATE)
log.Trace("Doing: MirrorUpdate")
@@ -1386,11 +1477,11 @@ func MirrorUpdate() {
// GitFsck calls 'git fsck' to check repository health.
func GitFsck() {
- if isGitFscking {
+ if taskStatusPool.IsRunning(_GIT_FSCK) {
return
}
- isGitFscking = true
- defer func() { isGitFscking = false }()
+ taskStatusPool.Start(_GIT_FSCK)
+ defer taskStatusPool.Stop(_GIT_FSCK)
log.Trace("Doing: GitFsck")
@@ -1455,11 +1546,11 @@ func repoStatsCheck(checker *repoChecker) {
}
func CheckRepoStats() {
- if isCheckingRepos {
+ if taskStatusPool.IsRunning(_CHECK_REPOs) {
return
}
- isCheckingRepos = true
- defer func() { isCheckingRepos = false }()
+ taskStatusPool.Start(_CHECK_REPOs)
+ defer taskStatusPool.Stop(_CHECK_REPOs)
log.Trace("Doing: CheckRepoStats")
@@ -1680,25 +1771,21 @@ func WatchRepo(uid, repoId int64, watch bool) (err error) {
return watchRepo(x, uid, repoId, watch)
}
-func getWatchers(e Engine, rid int64) ([]*Watch, error) {
+func getWatchers(e Engine, repoID int64) ([]*Watch, error) {
watches := make([]*Watch, 0, 10)
- err := e.Find(&watches, &Watch{RepoID: rid})
- return watches, err
+ return watches, e.Find(&watches, &Watch{RepoID: repoID})
}
// GetWatchers returns all watchers of given repository.
-func GetWatchers(rid int64) ([]*Watch, error) {
- return getWatchers(x, rid)
+func GetWatchers(repoID int64) ([]*Watch, error) {
+ return getWatchers(x, repoID)
}
-// Repository.GetWatchers returns all users watching given repository.
-func (repo *Repository) GetWatchers(offset int) ([]*User, error) {
- users := make([]*User, 0, 10)
- offset = (offset - 1) * ItemsPerPage
-
- err := x.Limit(ItemsPerPage, offset).Where("repo_id=?", repo.ID).Join("LEFT", "watch", "user.id=watch.user_id").Find(&users)
-
- return users, err
+// Repository.GetWatchers returns range of users watching given repository.
+func (repo *Repository) GetWatchers(page int) ([]*User, error) {
+ users := make([]*User, 0, ItemsPerPage)
+ return users, x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).
+ Where("repo_id=?", repo.ID).Join("LEFT", "watch", "user.id=watch.user_id").Find(&users)
}
func notifyWatchers(e Engine, act *Action) error {
@@ -1778,13 +1865,10 @@ func IsStaring(uid, repoId int64) bool {
return has
}
-func (repo *Repository) GetStars(offset int) ([]*User, error) {
- users := make([]*User, 0, 10)
- offset = (offset - 1) * ItemsPerPage
-
- err := x.Limit(ItemsPerPage, offset).Where("repo_id=?", repo.ID).Join("LEFT", "star", "user.id=star.uid").Find(&users)
-
- return users, err
+func (repo *Repository) GetStargazers(page int) ([]*User, error) {
+ users := make([]*User, 0, ItemsPerPage)
+ return users, x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).
+ Where("repo_id=?", repo.ID).Join("LEFT", "star", "user.id=star.uid").Find(&users)
}
// ___________ __
@@ -1856,9 +1940,6 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Reposit
}
func (repo *Repository) GetForks() ([]*Repository, error) {
- forks := make([]*Repository, 0, 10)
-
- err := x.Find(&forks, &Repository{ForkID: repo.ID})
-
- return forks, err
+ forks := make([]*Repository, 0, repo.NumForks)
+ return forks, x.Find(&forks, &Repository{ForkID: repo.ID})
}
diff --git a/models/update.go b/models/update.go
index 0cf62db4..14e56ce8 100644
--- a/models/update.go
+++ b/models/update.go
@@ -10,7 +10,6 @@ import (
"os/exec"
"strings"
- "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/git"
"github.com/gogits/gogs/modules/log"
)
@@ -28,6 +27,7 @@ func AddUpdateTask(task *UpdateTask) error {
return err
}
+// GetUpdateTaskByUUID returns update task by given UUID.
func GetUpdateTaskByUUID(uuid string) (*UpdateTask, error) {
task := &UpdateTask{
UUID: uuid,
@@ -36,7 +36,7 @@ func GetUpdateTaskByUUID(uuid string) (*UpdateTask, error) {
if err != nil {
return nil, err
} else if !has {
- return nil, fmt.Errorf("task does not exist: %s", uuid)
+ return nil, ErrUpdateTaskNotExist{uuid}
}
return task, nil
}
@@ -46,10 +46,10 @@ func DeleteUpdateTaskByUUID(uuid string) error {
return err
}
-func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName string, userId int64) error {
- isNew := strings.HasPrefix(oldCommitId, "0000000")
+func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName string, userID int64) error {
+ isNew := strings.HasPrefix(oldCommitID, "0000000")
if isNew &&
- strings.HasPrefix(newCommitId, "0000000") {
+ strings.HasPrefix(newCommitID, "0000000") {
return fmt.Errorf("old rev and new rev both 000000")
}
@@ -59,23 +59,23 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
gitUpdate.Dir = f
gitUpdate.Run()
- isDel := strings.HasPrefix(newCommitId, "0000000")
+ isDel := strings.HasPrefix(newCommitID, "0000000")
if isDel {
- log.GitLogger.Info("del rev", refName, "from", userName+"/"+repoName+".git", "by", userId)
+ log.GitLogger.Info("del rev", refName, "from", userName+"/"+repoName+".git", "by", userID)
return nil
}
- repo, err := git.OpenRepository(f)
+ gitRepo, err := git.OpenRepository(f)
if err != nil {
return fmt.Errorf("runUpdate.Open repoId: %v", err)
}
- ru, err := GetUserByName(repoUserName)
+ user, err := GetUserByName(repoUserName)
if err != nil {
return fmt.Errorf("runUpdate.GetUserByName: %v", err)
}
- repos, err := GetRepositoryByName(ru.Id, repoName)
+ repo, err := GetRepositoryByName(user.Id, repoName)
if err != nil {
return fmt.Errorf("runUpdate.GetRepositoryByName userId: %v", err)
}
@@ -83,7 +83,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
// Push tags.
if strings.HasPrefix(refName, "refs/tags/") {
tagName := git.RefEndName(refName)
- tag, err := repo.GetTag(tagName)
+ tag, err := gitRepo.GetTag(tagName)
if err != nil {
log.GitLogger.Fatal(4, "runUpdate.GetTag: %v", err)
}
@@ -99,16 +99,16 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
actEmail = cmt.Committer.Email
}
- commit := &base.PushCommits{}
+ commit := &PushCommits{}
- if err = CommitRepoAction(userId, ru.Id, userName, actEmail,
- repos.ID, repoUserName, repoName, refName, commit, oldCommitId, newCommitId); err != nil {
+ if err = CommitRepoAction(userID, user.Id, userName, actEmail,
+ repo.ID, repoUserName, repoName, refName, commit, oldCommitID, newCommitID); err != nil {
log.GitLogger.Fatal(4, "CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
}
return err
}
- newCommit, err := repo.GetCommit(newCommitId)
+ newCommit, err := gitRepo.GetCommit(newCommitID)
if err != nil {
return fmt.Errorf("runUpdate GetCommit of newCommitId: %v", err)
}
@@ -121,7 +121,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
return fmt.Errorf("CommitsBefore: %v", err)
}
} else {
- l, err = newCommit.CommitsBeforeUntil(oldCommitId)
+ l, err = newCommit.CommitsBeforeUntil(oldCommitID)
if err != nil {
return fmt.Errorf("CommitsBeforeUntil: %v", err)
}
@@ -132,7 +132,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
}
// Push commits.
- commits := make([]*base.PushCommit, 0)
+ commits := make([]*PushCommit, 0)
var actEmail string
for e := l.Front(); e != nil; e = e.Next() {
commit := e.Value.(*git.Commit)
@@ -140,15 +140,15 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
actEmail = commit.Committer.Email
}
commits = append(commits,
- &base.PushCommit{commit.Id.String(),
+ &PushCommit{commit.ID.String(),
commit.Message(),
commit.Author.Email,
commit.Author.Name,
})
}
- if err = CommitRepoAction(userId, ru.Id, userName, actEmail,
- repos.ID, repoUserName, repoName, refName, &base.PushCommits{l.Len(), commits, ""}, oldCommitId, newCommitId); err != nil {
+ if err = CommitRepoAction(userID, user.Id, userName, actEmail,
+ repo.ID, repoUserName, repoName, refName, &PushCommits{l.Len(), commits, "", nil}, oldCommitID, newCommitID); err != nil {
return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
}
return nil
diff --git a/models/user.go b/models/user.go
index 4109f4d9..750f59e5 100644
--- a/models/user.go
+++ b/models/user.go
@@ -14,6 +14,7 @@ import (
"image"
"image/jpeg"
_ "image/jpeg"
+ "image/png"
"os"
"path"
"path/filepath"
@@ -75,9 +76,10 @@ type User struct {
LastRepoVisibility bool
// Permissions.
- IsActive bool
- IsAdmin bool
- AllowGitHook bool
+ IsActive bool
+ IsAdmin bool
+ AllowGitHook bool
+ AllowImportLocal bool // Allow migrate repository by local path
// Avatar.
Avatar string `xorm:"VARCHAR(2048) NOT NULL"`
@@ -107,6 +109,22 @@ func (u *User) AfterSet(colName string, _ xorm.Cell) {
}
}
+// HasForkedRepo checks if user has already forked a repository with given ID.
+func (u *User) HasForkedRepo(repoID int64) bool {
+ _, has := HasForkedRepo(u.Id, repoID)
+ return has
+}
+
+// CanEditGitHook returns true if user can edit Git hooks.
+func (u *User) CanEditGitHook() bool {
+ return u.IsAdmin || u.AllowGitHook
+}
+
+// CanImportLocal returns true if user can migrate repository by local path.
+func (u *User) CanImportLocal() bool {
+ return u.IsAdmin || u.AllowImportLocal
+}
+
// EmailAdresses is the list of all email addresses of a user. Can contain the
// primary email address, but is not obligatory
type EmailAddress struct {
@@ -242,14 +260,12 @@ func (u *User) ValidatePassword(passwd string) bool {
// UploadAvatar saves custom avatar for user.
// FIXME: split uploads to different subdirs in case we have massive users.
func (u *User) UploadAvatar(data []byte) error {
- u.UseCustomAvatar = true
-
img, _, err := image.Decode(bytes.NewReader(data))
if err != nil {
- return err
+ return fmt.Errorf("Decode: %v", err)
}
- m := resize.Resize(234, 234, img, resize.NearestNeighbor)
+ m := resize.Resize(290, 290, img, resize.NearestNeighbor)
sess := x.NewSession()
defer sessionRelease(sess)
@@ -257,19 +273,20 @@ func (u *User) UploadAvatar(data []byte) error {
return err
}
- if _, err = sess.Id(u.Id).AllCols().Update(u); err != nil {
- return err
+ u.UseCustomAvatar = true
+ if err = updateUser(sess, u); err != nil {
+ return fmt.Errorf("updateUser: %v", err)
}
os.MkdirAll(setting.AvatarUploadPath, os.ModePerm)
fw, err := os.Create(u.CustomAvatarPath())
if err != nil {
- return err
+ return fmt.Errorf("Create: %v", err)
}
defer fw.Close()
- if err = jpeg.Encode(fw, m, nil); err != nil {
- return err
+ if err = png.Encode(fw, m); err != nil {
+ return fmt.Errorf("Encode: %v", err)
}
return sess.Commit()
@@ -356,6 +373,15 @@ func (u *User) DisplayName() string {
return u.Name
}
+// ShortName returns shorted user name with given maximum length,
+// it adds "..." at the end if user name has more length than maximum.
+func (u *User) ShortName(length int) string {
+ if len(u.Name) < length {
+ return u.Name
+ }
+ return u.Name[:length] + "..."
+}
+
// IsUserExist checks if given user name exist,
// the user name should be noncased unique.
// If uid is presented, then check will rule out that one,
@@ -717,9 +743,9 @@ func UserPath(userName string) string {
return filepath.Join(setting.RepoRootPath, strings.ToLower(userName))
}
-func GetUserByKeyId(keyId int64) (*User, error) {
+func GetUserByKeyID(keyID int64) (*User, error) {
user := new(User)
- has, err := x.Sql("SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?", keyId).Get(user)
+ has, err := x.Sql("SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?", keyID).Get(user)
if err != nil {
return nil, err
} else if !has {
@@ -980,7 +1006,7 @@ func GetUserByEmail(email string) (*User, error) {
return GetUserByID(emailAddress.UID)
}
- return nil, ErrUserNotExist{0, "email"}
+ return nil, ErrUserNotExist{0, email}
}
// SearchUserByName returns given number of users whose name contains keyword.
diff --git a/models/webhook.go b/models/webhook.go
index b4d7dc9c..cbc874a9 100644
--- a/models/webhook.go
+++ b/models/webhook.go
@@ -178,8 +178,8 @@ func GetActiveWebhooksByRepoID(repoID int64) (ws []*Webhook, err error) {
return ws, err
}
-// GetWebhooksByRepoId returns all webhooks of repository.
-func GetWebhooksByRepoId(repoID int64) (ws []*Webhook, err error) {
+// GetWebhooksByRepoID returns all webhooks of repository.
+func GetWebhooksByRepoID(repoID int64) (ws []*Webhook, err error) {
err = x.Find(&ws, &Webhook{RepoID: repoID})
return ws, err
}