aboutsummaryrefslogtreecommitdiff
path: root/models
diff options
context:
space:
mode:
Diffstat (limited to 'models')
-rw-r--r--models/action.go25
-rw-r--r--models/admin.go24
-rw-r--r--models/error.go20
-rw-r--r--models/git_diff.go9
-rw-r--r--models/git_diff_test.go100
-rw-r--r--models/issue.go1
-rw-r--r--models/models.go7
-rw-r--r--models/org.go82
-rw-r--r--models/pull.go9
-rw-r--r--models/repo.go114
-rw-r--r--models/repo_branch.go57
-rw-r--r--models/ssh_key.go8
-rw-r--r--models/update.go90
-rw-r--r--models/user.go21
-rw-r--r--models/webhook.go7
15 files changed, 426 insertions, 148 deletions
diff --git a/models/action.go b/models/action.go
index 33d5246e..3bcf999d 100644
--- a/models/action.go
+++ b/models/action.go
@@ -498,7 +498,7 @@ func CommitRepoAction(
payloadSender := &api.PayloadUser{
UserName: pusher.Name,
ID: pusher.Id,
- AvatarUrl: setting.AppUrl + pusher.RelAvatarLink(),
+ AvatarUrl: pusher.AvatarLink(),
}
switch opType {
@@ -593,12 +593,29 @@ func MergePullRequestAction(actUser *User, repo *Repository, pull *Issue) error
}
// GetFeeds returns action list of given user in given context.
-func GetFeeds(uid, offset int64, isProfile bool) ([]*Action, error) {
+// userID is the user who's requesting, ctxUserID is the user/org that is requested.
+// userID can be -1, if isProfile is true or in order to skip the permission check.
+func GetFeeds(ctxUserID, userID, offset int64, isProfile bool) ([]*Action, error) {
actions := make([]*Action, 0, 20)
- sess := x.Limit(20, int(offset)).Desc("id").Where("user_id=?", uid)
+ sess := x.Limit(20, int(offset)).Desc("id").Where("user_id=?", ctxUserID)
if isProfile {
- sess.And("is_private=?", false).And("act_user_id=?", uid)
+ sess.And("is_private=?", false).And("act_user_id=?", ctxUserID)
+ } else if ctxUserID != -1 {
+ ctxUser := &User{Id: ctxUserID}
+ if err := ctxUser.GetUserRepositories(userID); err != nil {
+ return nil, err
+ }
+
+ var repoIDs []int64
+ for _, repo := range ctxUser.Repos {
+ repoIDs = append(repoIDs, repo.ID)
+ }
+
+ if len(repoIDs) > 0 {
+ sess.In("repo_id", repoIDs)
+ }
}
+
err := sess.Find(&actions)
return actions, err
}
diff --git a/models/admin.go b/models/admin.go
index 1d6bf629..7756cd6a 100644
--- a/models/admin.go
+++ b/models/admin.go
@@ -5,12 +5,17 @@
package models
import (
+ "fmt"
+ "os"
+ "os/exec"
"strings"
"time"
"github.com/Unknwon/com"
"github.com/gogits/gogs/modules/base"
+ "github.com/gogits/gogs/modules/log"
+ "github.com/gogits/gogs/modules/setting"
)
type NoticeType int
@@ -47,6 +52,25 @@ func CreateRepositoryNotice(desc string) error {
return CreateNotice(NOTICE_REPOSITORY, desc)
}
+// RemoveAllWithNotice removes all directories in given path and
+// creates a system notice when error occurs.
+func RemoveAllWithNotice(title, path string) {
+ var err error
+ if setting.IsWindows {
+ err = exec.Command("cmd", "/C", "rmdir", "/S", "/Q", path).Run()
+ } else {
+ err = os.RemoveAll(path)
+ }
+
+ if err != nil {
+ desc := fmt.Sprintf("%s [%s]: %v", title, path, err)
+ log.Warn(desc)
+ if err = CreateRepositoryNotice(desc); err != nil {
+ log.Error(4, "CreateRepositoryNotice: %v", err)
+ }
+ }
+}
+
// CountNotices returns number of notices.
func CountNotices() int64 {
count, _ := x.Count(new(Notice))
diff --git a/models/error.go b/models/error.go
index 8e2048de..cd7fa35d 100644
--- a/models/error.go
+++ b/models/error.go
@@ -392,6 +392,26 @@ func (err ErrReleaseNotExist) Error() string {
return fmt.Sprintf("Release tag does not exist [id: %d, tag_name: %s]", err.ID, err.TagName)
}
+// __________ .__
+// \______ \____________ ____ ____ | |__
+// | | _/\_ __ \__ \ / \_/ ___\| | \
+// | | \ | | \// __ \| | \ \___| Y \
+// |______ / |__| (____ /___| /\___ >___| /
+// \/ \/ \/ \/ \/
+
+type ErrBranchNotExist struct {
+ Name string
+}
+
+func IsErrBranchNotExist(err error) bool {
+ _, ok := err.(ErrBranchNotExist)
+ return ok
+}
+
+func (err ErrBranchNotExist) Error() string {
+ return fmt.Sprintf("Branch does not exist [name: %s]", err.Name)
+}
+
// __ __ ___. .__ __
// / \ / \ ____\_ |__ | |__ ____ ____ | | __
// \ \/\/ // __ \| __ \| | \ / _ \ / _ \| |/ /
diff --git a/models/git_diff.go b/models/git_diff.go
index e8bfe610..9796ef59 100644
--- a/models/git_diff.go
+++ b/models/git_diff.go
@@ -26,6 +26,7 @@ import (
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/process"
+ "github.com/gogits/gogs/modules/template/highlight"
)
type DiffLineType uint8
@@ -160,12 +161,20 @@ type DiffFile struct {
IsBin bool
IsRenamed bool
Sections []*DiffSection
+ HighlightClass string
}
func (diffFile *DiffFile) GetType() int {
return int(diffFile.Type)
}
+func (diffFile *DiffFile) GetHighlightClass() string {
+ if diffFile.HighlightClass == "" {
+ diffFile.HighlightClass = highlight.FileNameToHighlightClass(diffFile.Name)
+ }
+ return diffFile.HighlightClass
+}
+
type Diff struct {
TotalAddition, TotalDeletion int
Files []*DiffFile
diff --git a/models/git_diff_test.go b/models/git_diff_test.go
index 4084814e..3a1312ca 100644
--- a/models/git_diff_test.go
+++ b/models/git_diff_test.go
@@ -1,70 +1,70 @@
package models
import (
- dmp "github.com/sergi/go-diff/diffmatchpatch"
- "html/template"
- "testing"
+ dmp "github.com/sergi/go-diff/diffmatchpatch"
+ "html/template"
+ "testing"
)
func assertEqual(t *testing.T, s1 string, s2 template.HTML) {
- if s1 != string(s2) {
- t.Errorf("%s should be equal %s", s2, s1)
- }
+ if s1 != string(s2) {
+ t.Errorf("%s should be equal %s", s2, s1)
+ }
}
func assertLineEqual(t *testing.T, d1 *DiffLine, d2 *DiffLine) {
- if d1 != d2 {
- t.Errorf("%v should be equal %v", d1, d2)
- }
+ if d1 != d2 {
+ t.Errorf("%v should be equal %v", d1, d2)
+ }
}
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"},
- }, DIFF_LINE_ADD))
+ 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"},
+ }, DIFF_LINE_ADD))
- 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"},
- }, DIFF_LINE_DEL))
+ 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"},
+ }, DIFF_LINE_DEL))
}
// test if GetLine is return the correct lines
func TestGetLine(t *testing.T) {
- ds := DiffSection{Lines: []*DiffLine{
- &DiffLine{LeftIdx: 28, RightIdx: 28, Type: DIFF_LINE_PLAIN},
- &DiffLine{LeftIdx: 29, RightIdx: 29, Type: DIFF_LINE_PLAIN},
- &DiffLine{LeftIdx: 30, RightIdx: 30, Type: DIFF_LINE_PLAIN},
- &DiffLine{LeftIdx: 31, RightIdx: 0, Type: DIFF_LINE_DEL},
- &DiffLine{LeftIdx: 0, RightIdx: 31, Type: DIFF_LINE_ADD},
- &DiffLine{LeftIdx: 0, RightIdx: 32, Type: DIFF_LINE_ADD},
- &DiffLine{LeftIdx: 32, RightIdx: 33, Type: DIFF_LINE_PLAIN},
- &DiffLine{LeftIdx: 33, RightIdx: 0, Type: DIFF_LINE_DEL},
- &DiffLine{LeftIdx: 34, RightIdx: 0, Type: DIFF_LINE_DEL},
- &DiffLine{LeftIdx: 35, RightIdx: 0, Type: DIFF_LINE_DEL},
- &DiffLine{LeftIdx: 36, RightIdx: 0, Type: DIFF_LINE_DEL},
- &DiffLine{LeftIdx: 0, RightIdx: 34, Type: DIFF_LINE_ADD},
- &DiffLine{LeftIdx: 0, RightIdx: 35, Type: DIFF_LINE_ADD},
- &DiffLine{LeftIdx: 0, RightIdx: 36, Type: DIFF_LINE_ADD},
- &DiffLine{LeftIdx: 0, RightIdx: 37, Type: DIFF_LINE_ADD},
- &DiffLine{LeftIdx: 37, RightIdx: 38, Type: DIFF_LINE_PLAIN},
- &DiffLine{LeftIdx: 38, RightIdx: 39, Type: DIFF_LINE_PLAIN},
- }}
+ ds := DiffSection{Lines: []*DiffLine{
+ &DiffLine{LeftIdx: 28, RightIdx: 28, Type: DIFF_LINE_PLAIN},
+ &DiffLine{LeftIdx: 29, RightIdx: 29, Type: DIFF_LINE_PLAIN},
+ &DiffLine{LeftIdx: 30, RightIdx: 30, Type: DIFF_LINE_PLAIN},
+ &DiffLine{LeftIdx: 31, RightIdx: 0, Type: DIFF_LINE_DEL},
+ &DiffLine{LeftIdx: 0, RightIdx: 31, Type: DIFF_LINE_ADD},
+ &DiffLine{LeftIdx: 0, RightIdx: 32, Type: DIFF_LINE_ADD},
+ &DiffLine{LeftIdx: 32, RightIdx: 33, Type: DIFF_LINE_PLAIN},
+ &DiffLine{LeftIdx: 33, RightIdx: 0, Type: DIFF_LINE_DEL},
+ &DiffLine{LeftIdx: 34, RightIdx: 0, Type: DIFF_LINE_DEL},
+ &DiffLine{LeftIdx: 35, RightIdx: 0, Type: DIFF_LINE_DEL},
+ &DiffLine{LeftIdx: 36, RightIdx: 0, Type: DIFF_LINE_DEL},
+ &DiffLine{LeftIdx: 0, RightIdx: 34, Type: DIFF_LINE_ADD},
+ &DiffLine{LeftIdx: 0, RightIdx: 35, Type: DIFF_LINE_ADD},
+ &DiffLine{LeftIdx: 0, RightIdx: 36, Type: DIFF_LINE_ADD},
+ &DiffLine{LeftIdx: 0, RightIdx: 37, Type: DIFF_LINE_ADD},
+ &DiffLine{LeftIdx: 37, RightIdx: 38, Type: DIFF_LINE_PLAIN},
+ &DiffLine{LeftIdx: 38, RightIdx: 39, Type: DIFF_LINE_PLAIN},
+ }}
- assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 31), ds.Lines[4])
- assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 31), ds.Lines[3])
+ assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 31), ds.Lines[4])
+ assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 31), ds.Lines[3])
- assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 33), ds.Lines[11])
- assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 34), ds.Lines[12])
- assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 35), ds.Lines[13])
- assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 36), ds.Lines[14])
- assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 34), ds.Lines[7])
- assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 35), ds.Lines[8])
- assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 36), ds.Lines[9])
- assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 37), ds.Lines[10])
+ assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 33), ds.Lines[11])
+ assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 34), ds.Lines[12])
+ assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 35), ds.Lines[13])
+ assertLineEqual(t, ds.GetLine(DIFF_LINE_ADD, 36), ds.Lines[14])
+ assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 34), ds.Lines[7])
+ assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 35), ds.Lines[8])
+ assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 36), ds.Lines[9])
+ assertLineEqual(t, ds.GetLine(DIFF_LINE_DEL, 37), ds.Lines[10])
}
diff --git a/models/issue.go b/models/issue.go
index 6188da5c..32645463 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -1179,6 +1179,7 @@ func (m *Milestone) AfterSet(colName string, _ xorm.Cell) {
if m.Deadline.Year() == 9999 {
return
}
+ m.Deadline = regulateTimeZone(m.Deadline)
m.DeadlineString = m.Deadline.Format("2006-01-02")
if time.Now().After(m.Deadline) {
diff --git a/models/models.go b/models/models.go
index 2249fee4..2e91f716 100644
--- a/models/models.go
+++ b/models/models.go
@@ -191,12 +191,7 @@ func SetEngine() (err error) {
return fmt.Errorf("Fail to create xorm.log: %v", err)
}
x.SetLogger(xorm.NewSimpleLogger(f))
-
- x.ShowSQL = true
- x.ShowInfo = true
- x.ShowDebug = true
- x.ShowErr = true
- x.ShowWarn = true
+ x.ShowSQL(true)
return nil
}
diff --git a/models/org.go b/models/org.go
index b8836c34..9d86df10 100644
--- a/models/org.go
+++ b/models/org.go
@@ -10,6 +10,7 @@ import (
"os"
"strings"
+ "github.com/Unknwon/com"
"github.com/go-xorm/xorm"
)
@@ -253,6 +254,27 @@ func IsPublicMembership(orgId, uid int64) bool {
return has
}
+func getOrgsByUserID(sess *xorm.Session, userID int64, showAll bool) ([]*User, error) {
+ orgs := make([]*User, 0, 10)
+ if !showAll {
+ sess.And("`org_user`.is_public=?", true)
+ }
+ return orgs, sess.And("`org_user`.uid=?", userID).
+ Join("INNER", "`org_user`", "`org_user`.org_id=`user`.id").Find(&orgs)
+}
+
+// GetOrgsByUserID returns a list of organizations that the given user ID
+// has joined.
+func GetOrgsByUserID(userID int64, showAll bool) ([]*User, error) {
+ return getOrgsByUserID(x.NewSession(), userID, showAll)
+}
+
+// GetOrgsByUserIDDesc returns a list of organizations that the given user ID
+// has joined, ordered descending by the given condition.
+func GetOrgsByUserIDDesc(userID int64, desc string, showAll bool) ([]*User, error) {
+ return getOrgsByUserID(x.NewSession().Desc(desc), userID, showAll)
+}
+
func getOwnedOrgsByUserID(sess *xorm.Session, userID int64) ([]*User, error) {
orgs := make([]*User, 0, 10)
return orgs, sess.Where("`org_user`.uid=?", userID).And("`org_user`.is_owner=?", true).
@@ -266,7 +288,7 @@ func GetOwnedOrgsByUserID(userID int64) ([]*User, error) {
}
// GetOwnedOrganizationsByUserIDDesc returns a list of organizations are owned by
-// given user ID and descring order by given condition.
+// given user ID, ordered descending by the given condition.
func GetOwnedOrgsByUserIDDesc(userID int64, desc string) ([]*User, error) {
sess := x.NewSession()
return getOwnedOrgsByUserID(sess.Desc(desc), userID)
@@ -1028,3 +1050,61 @@ func removeOrgRepo(e Engine, orgID, repoID int64) error {
func RemoveOrgRepo(orgID, repoID int64) error {
return removeOrgRepo(x, orgID, repoID)
}
+
+// GetUserRepositories gets all repositories of an organization,
+// that the user with the given userID has access to.
+func (org *User) GetUserRepositories(userID int64) (err error) {
+ teams := make([]*Team, 0, 10)
+ if err = x.Cols("`team`.id").
+ Where("`team_user`.org_id=?", org.Id).
+ And("`team_user`.uid=?", userID).
+ Join("INNER", "`team_user`", "`team_user`.team_id=`team`.id").
+ Find(&teams); err != nil {
+ return fmt.Errorf("GetUserRepositories: get teams: %v", err)
+ }
+
+ teamIDs := make([]string, len(teams))
+ for i := range teams {
+ teamIDs[i] = com.ToStr(teams[i].ID)
+ }
+ if len(teamIDs) == 0 {
+ // user has no team but "IN ()" is invalid SQL
+ teamIDs = append(teamIDs, "-1") // there is no repo with id=-1
+ }
+
+ // Due to a bug in xorm using IN() together with OR() is impossible.
+ // As a workaround, we have to build the IN statement on our own, until this is fixed.
+ // https://github.com/go-xorm/xorm/issues/342
+
+ if err = x.Cols("`repository`.*").
+ Join("INNER", "`team_repo`", "`team_repo`.repo_id=`repository`.id").
+ Where("`repository`.owner_id=?", org.Id).
+ And("`repository`.is_private=?", false).
+ Or("`team_repo`.team_id=(?)", strings.Join(teamIDs, ",")).
+ GroupBy("`repository`.id").
+ Find(&org.Repos); err != nil {
+ return fmt.Errorf("GetUserRepositories: get repositories: %v", err)
+ }
+
+ // FIXME: should I change this value inside method,
+ // or only in location of caller where it's really needed?
+ org.NumRepos = len(org.Repos)
+ return nil
+}
+
+// GetTeams returns all teams that belong to organization,
+// and that the user has joined.
+func (org *User) GetUserTeams(userID int64) error {
+ if err := x.Cols("`team`.*").
+ Where("`team_user`.org_id=?", org.Id).
+ And("`team_user`.uid=?", userID).
+ Join("INNER", "`team_user`", "`team_user`.team_id=`team`.id").
+ Find(&org.Teams); err != nil {
+ return fmt.Errorf("GetUserTeams: %v", err)
+ }
+
+ // FIXME: should I change this value inside method,
+ // or only in location of caller where it's really needed?
+ org.NumTeams = len(org.Teams)
+ return nil
+}
diff --git a/models/pull.go b/models/pull.go
index c52c871c..67f103e8 100644
--- a/models/pull.go
+++ b/models/pull.go
@@ -257,6 +257,7 @@ var patchConflicts = []string{
"patch does not apply",
"already exists in working directory",
"unrecognized input",
+ "error:",
}
// testPatch checks if patch can be merged to base repository without conflit.
@@ -280,7 +281,7 @@ func (pr *PullRequest) testPatch() (err error) {
return nil
}
- log.Trace("PullRequest[%d].testPatch(patchPath): %s", pr.ID, patchPath)
+ log.Trace("PullRequest[%d].testPatch (patchPath): %s", pr.ID, patchPath)
if err := pr.BaseRepo.UpdateLocalCopy(); err != nil {
return fmt.Errorf("UpdateLocalCopy: %v", err)
@@ -288,7 +289,7 @@ func (pr *PullRequest) testPatch() (err error) {
// Checkout base branch.
_, stderr, err := process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
- fmt.Sprintf("PullRequest.Merge(git checkout): %v", pr.BaseRepo.ID),
+ fmt.Sprintf("PullRequest.Merge (git checkout): %v", pr.BaseRepo.ID),
"git", "checkout", pr.BaseBranch)
if err != nil {
return fmt.Errorf("git checkout: %s", stderr)
@@ -296,12 +297,12 @@ func (pr *PullRequest) testPatch() (err error) {
pr.Status = PULL_REQUEST_STATUS_CHECKING
_, stderr, err = process.ExecDir(-1, pr.BaseRepo.LocalCopyPath(),
- fmt.Sprintf("testPatch(git apply --check): %d", pr.BaseRepo.ID),
+ fmt.Sprintf("testPatch (git apply --check): %d", pr.BaseRepo.ID),
"git", "apply", "--check", patchPath)
if err != nil {
for i := range patchConflicts {
if strings.Contains(stderr, patchConflicts[i]) {
- log.Trace("PullRequest[%d].testPatch(apply): has conflit", pr.ID)
+ log.Trace("PullRequest[%d].testPatch (apply): has conflit", pr.ID)
fmt.Println(stderr)
pr.Status = PULL_REQUEST_STATUS_CONFLICT
return nil
diff --git a/models/repo.go b/models/repo.go
index 8ce1f719..98bb1107 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -332,7 +332,17 @@ func (repo *Repository) IsOwnedBy(userID int64) bool {
// CanBeForked returns true if repository meets the requirements of being forked.
func (repo *Repository) CanBeForked() bool {
- return !repo.IsBare && !repo.IsMirror
+ return !repo.IsBare
+}
+
+// CanEnablePulls returns true if repository meets the requirements of accepting pulls.
+func (repo *Repository) CanEnablePulls() bool {
+ return !repo.IsMirror
+}
+
+// AllowPulls returns true if repository meets the requirements of accepting pulls and has them enabled.
+func (repo *Repository) AllowsPulls() bool {
+ return repo.CanEnablePulls() && repo.EnablePulls;
}
func (repo *Repository) NextIssueIndex() int64 {
@@ -414,7 +424,8 @@ func (repo *Repository) ComposePayload() *api.PayloadRepo {
Email: repo.MustOwner().Email,
UserName: repo.MustOwner().Name,
},
- Private: repo.IsPrivate,
+ Private: repo.IsPrivate,
+ DefaultBranch: repo.DefaultBranch,
}
}
@@ -591,6 +602,11 @@ func UpdateMirror(m *Mirror) error {
return updateMirror(x, m)
}
+func DeleteMirrorByRepoID(repoID int64) error {
+ _, err := x.Delete(&Mirror{RepoID: repoID})
+ return err
+}
+
func createUpdateHook(repoPath string) error {
return git.SetUpdateHook(repoPath,
fmt.Sprintf(_TPL_UPDATE_HOOK, setting.ScriptType, "\""+setting.AppPath+"\"", setting.CustomConf))
@@ -654,7 +670,12 @@ func MigrateRepository(u *User, opts MigrateRepoOptions) (*Repository, error) {
return repo, UpdateRepository(repo, false)
}
- if err = createUpdateHook(repoPath); err != nil {
+ return CleanUpMigrateInfo(repo, repoPath)
+}
+
+// Finish migrating repository with things that don't need to be done for mirrors.
+func CleanUpMigrateInfo(repo *Repository, repoPath string) (*Repository, error) {
+ if err := createUpdateHook(repoPath); err != nil {
return repo, fmt.Errorf("createUpdateHook: %v", err)
}
@@ -957,10 +978,13 @@ func countRepositories(showPrivate bool) int64 {
sess := x.NewSession()
if !showPrivate {
- sess.Where("is_private=", false)
+ sess.Where("is_private=?", false)
}
- count, _ := sess.Count(new(Repository))
+ count, err := sess.Count(new(Repository))
+ if err != nil {
+ log.Error(4, "countRepositories: %v", err)
+ }
return count
}
@@ -1093,13 +1117,16 @@ func TransferOwnership(u *User, newOwnerName string, repo *Repository) error {
return fmt.Errorf("transferRepoAction: %v", err)
}
- // Change repository directory name.
+ // Rename remote repository to new path and delete local copy.
if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil {
return fmt.Errorf("rename repository directory: %v", err)
}
+ RemoveAllWithNotice("Delete repository local copy", repo.LocalCopyPath())
+ // Rename remote wiki repository to new path and delete local copy.
wikiPath := WikiPath(owner.Name, repo.Name)
if com.IsExist(wikiPath) {
+ RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
if err = os.Rename(wikiPath, WikiPath(newOwner.Name, repo.Name)); err != nil {
return fmt.Errorf("rename repository wiki: %v", err)
}
@@ -1123,16 +1150,22 @@ func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error)
return ErrRepoAlreadyExist{u.Name, newRepoName}
}
+ repo, err := GetRepositoryByName(u.Id, oldRepoName)
+ if err != nil {
+ return fmt.Errorf("GetRepositoryByName: %v", err)
+ }
+
// Change repository directory name.
- if err = os.Rename(RepoPath(u.Name, oldRepoName), RepoPath(u.Name, newRepoName)); err != nil {
+ if err = os.Rename(repo.RepoPath(), RepoPath(u.Name, newRepoName)); err != nil {
return fmt.Errorf("rename repository directory: %v", err)
}
- wikiPath := WikiPath(u.Name, oldRepoName)
+ wikiPath := repo.WikiPath()
if com.IsExist(wikiPath) {
if err = os.Rename(wikiPath, WikiPath(u.Name, newRepoName)); err != nil {
return fmt.Errorf("rename repository wiki: %v", err)
}
+ RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
}
return nil
@@ -1295,30 +1328,16 @@ func DeleteRepository(uid, repoID int64) error {
// Remove repository files.
repoPath := repo.repoPath(sess)
- if err = os.RemoveAll(repoPath); err != nil {
- desc := fmt.Sprintf("delete repository files [%s]: %v", repoPath, err)
- log.Warn(desc)
- if err = CreateRepositoryNotice(desc); err != nil {
- log.Error(4, "CreateRepositoryNotice: %v", err)
- }
- }
+ RemoveAllWithNotice("Delete repository files", repoPath)
wikiPaths := []string{repo.WikiPath(), repo.LocalWikiPath()}
for _, wikiPath := range wikiPaths {
- if err = os.RemoveAll(wikiPath); err != nil {
- desc := fmt.Sprintf("delete repository wiki [%s]: %v", wikiPath, err)
- log.Warn(desc)
- if err = CreateRepositoryNotice(desc); err != nil {
- log.Error(4, "CreateRepositoryNotice: %v", err)
- }
- }
+ RemoveAllWithNotice("Delete repository wiki", wikiPath)
}
// Remove attachment files.
for i := range attachmentPaths {
- if err = os.Remove(attachmentPaths[i]); err != nil {
- log.Warn("delete attachment: %v", err)
- }
+ RemoveAllWithNotice("Delete attachment", attachmentPaths[i])
}
if err = sess.Commit(); err != nil {
@@ -1333,7 +1352,7 @@ func DeleteRepository(uid, repoID int64) error {
}
for i := range forkRepos {
if err = DeleteRepository(forkRepos[i].OwnerID, forkRepos[i].ID); err != nil {
- log.Error(4, "updateRepository[%d]: %v", forkRepos[i].ID, err)
+ log.Error(4, "DeleteRepository [%d]: %v", forkRepos[i].ID, err)
}
}
} else {
@@ -1457,9 +1476,8 @@ func DeleteRepositoryArchives() error {
})
}
-// DeleteMissingRepositories deletes all repository records that lost Git files.
-func DeleteMissingRepositories() error {
- repos := make([]*Repository, 0, 5)
+func gatherMissingRepoRecords() ([]*Repository, error) {
+ repos := make([]*Repository, 0, 10)
if err := x.Where("id > 0").Iterate(new(Repository),
func(idx int, bean interface{}) error {
repo := bean.(*Repository)
@@ -1468,10 +1486,18 @@ func DeleteMissingRepositories() error {
}
return nil
}); err != nil {
- if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteMissingRepositories: %v", err)); err2 != nil {
- log.Error(4, "CreateRepositoryNotice: %v", err2)
+ if err2 := CreateRepositoryNotice(fmt.Sprintf("gatherMissingRepoRecords: %v", err)); err2 != nil {
+ return nil, fmt.Errorf("CreateRepositoryNotice: %v", err)
}
- return nil
+ }
+ return repos, nil
+}
+
+// DeleteMissingRepositories deletes all repository records that lost Git files.
+func DeleteMissingRepositories() error {
+ repos, err := gatherMissingRepoRecords()
+ if err != nil {
+ return fmt.Errorf("gatherMissingRepoRecords: %v", err)
}
if len(repos) == 0 {
@@ -1482,7 +1508,29 @@ func DeleteMissingRepositories() error {
log.Trace("Deleting %d/%d...", repo.OwnerID, repo.ID)
if err := DeleteRepository(repo.OwnerID, repo.ID); err != nil {
if err2 := CreateRepositoryNotice(fmt.Sprintf("DeleteRepository [%d]: %v", repo.ID, err)); err2 != nil {
- log.Error(4, "CreateRepositoryNotice: %v", err2)
+ return fmt.Errorf("CreateRepositoryNotice: %v", err)
+ }
+ }
+ }
+ return nil
+}
+
+// ReinitMissingRepositories reinitializes all repository records that lost Git files.
+func ReinitMissingRepositories() error {
+ repos, err := gatherMissingRepoRecords()
+ if err != nil {
+ return fmt.Errorf("gatherMissingRepoRecords: %v", err)
+ }
+
+ if len(repos) == 0 {
+ return nil
+ }
+
+ for _, repo := range repos {
+ log.Trace("Initializing %d/%d...", repo.OwnerID, repo.ID)
+ if err := git.InitRepository(repo.RepoPath(), true); err != nil {
+ if err2 := CreateRepositoryNotice(fmt.Sprintf("InitRepository [%d]: %v", repo.ID, err)); err2 != nil {
+ return fmt.Errorf("CreateRepositoryNotice: %v", err)
}
}
}
diff --git a/models/repo_branch.go b/models/repo_branch.go
new file mode 100644
index 00000000..9cf2e9c4
--- /dev/null
+++ b/models/repo_branch.go
@@ -0,0 +1,57 @@
+// Copyright 2016 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package models
+
+import (
+ "github.com/gogits/git-module"
+)
+
+type Branch struct {
+ Path string
+ Name string
+}
+
+func GetBranchesByPath(path string) ([]*Branch, error) {
+ gitRepo, err := git.OpenRepository(path)
+ if err != nil {
+ return nil, err
+ }
+
+ brs, err := gitRepo.GetBranches()
+ if err != nil {
+ return nil, err
+ }
+
+ branches := make([]*Branch, len(brs))
+ for i := range brs {
+ branches[i] = &Branch{
+ Path: path,
+ Name: brs[i],
+ }
+ }
+ return branches, nil
+}
+
+func (repo *Repository) GetBranch(br string) (*Branch, error) {
+ if !git.IsBranchExist(repo.RepoPath(), br) {
+ return nil, &ErrBranchNotExist{br}
+ }
+ return &Branch{
+ Path: repo.RepoPath(),
+ Name: br,
+ }, nil
+}
+
+func (repo *Repository) GetBranches() ([]*Branch, error) {
+ return GetBranchesByPath(repo.RepoPath())
+}
+
+func (br *Branch) GetCommit() (*git.Commit, error) {
+ gitRepo, err := git.OpenRepository(br.Path)
+ if err != nil {
+ return nil, err
+ }
+ return gitRepo.GetBranchCommit(br.Name)
+}
diff --git a/models/ssh_key.go b/models/ssh_key.go
index a7b1680f..325a40a4 100644
--- a/models/ssh_key.go
+++ b/models/ssh_key.go
@@ -165,6 +165,9 @@ func CheckPublicKeyString(content string) (_ string, err error) {
return "", errors.New("only a single line with a single key please")
}
+ // remove any unnecessary whitespace now
+ content = strings.TrimSpace(content)
+
fields := strings.Fields(content)
if len(fields) < 2 {
return "", errors.New("too less fields")
@@ -374,6 +377,11 @@ func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error {
break
}
}
+
+ if !isFound {
+ log.Warn("SSH key %d not found in authorized_keys file for deletion", key.ID)
+ }
+
return nil
}
diff --git a/models/update.go b/models/update.go
index 5c6ea7f6..66775ea9 100644
--- a/models/update.go
+++ b/models/update.go
@@ -10,7 +10,7 @@ import (
"os/exec"
"strings"
- "github.com/gogits/git-module"
+ git "github.com/gogits/git-module"
"github.com/gogits/gogs/modules/log"
)
@@ -65,94 +65,104 @@ func ListToPushCommits(l *list.List) *PushCommits {
return &PushCommits{l.Len(), commits, "", nil}
}
-func Update(refName, oldCommitID, newCommitID, userName, repoUserName, repoName string, userID int64) error {
- isNew := strings.HasPrefix(oldCommitID, "0000000")
- if isNew &&
- strings.HasPrefix(newCommitID, "0000000") {
- return fmt.Errorf("old rev and new rev both 000000")
+type PushUpdateOptions struct {
+ RefName string
+ OldCommitID string
+ NewCommitID string
+ PusherID int64
+ PusherName string
+ RepoUserName string
+ RepoName string
+}
+
+// PushUpdate must be called for any push actions in order to
+// generates necessary push action history feeds.
+func PushUpdate(opts PushUpdateOptions) (err error) {
+ isNewRef := strings.HasPrefix(opts.OldCommitID, "0000000")
+ isDelRef := strings.HasPrefix(opts.NewCommitID, "0000000")
+ if isNewRef && isDelRef {
+ return fmt.Errorf("Old and new revisions both start with 000000")
}
- f := RepoPath(repoUserName, repoName)
+ repoPath := RepoPath(opts.RepoUserName, opts.RepoName)
gitUpdate := exec.Command("git", "update-server-info")
- gitUpdate.Dir = f
- gitUpdate.Run()
+ gitUpdate.Dir = repoPath
+ if err = gitUpdate.Run(); err != nil {
+ return fmt.Errorf("Fail to call 'git update-server-info': %v", err)
+ }
- isDel := strings.HasPrefix(newCommitID, "0000000")
- if isDel {
- log.GitLogger.Info("del rev", refName, "from", userName+"/"+repoName+".git", "by", userID)
+ if isDelRef {
+ log.GitLogger.Info("Reference '%s' has been deleted from '%s/%s' by %d",
+ opts.RefName, opts.RepoUserName, opts.RepoName, opts.PusherName)
return nil
}
- gitRepo, err := git.OpenRepository(f)
+ gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
- return fmt.Errorf("runUpdate.Open repoId: %v", err)
+ return fmt.Errorf("OpenRepository: %v", err)
}
- user, err := GetUserByName(repoUserName)
+ repoUser, err := GetUserByName(opts.RepoUserName)
if err != nil {
- return fmt.Errorf("runUpdate.GetUserByName: %v", err)
+ return fmt.Errorf("GetUserByName: %v", err)
}
- repo, err := GetRepositoryByName(user.Id, repoName)
+ repo, err := GetRepositoryByName(repoUser.Id, opts.RepoName)
if err != nil {
- return fmt.Errorf("runUpdate.GetRepositoryByName userId: %v", err)
+ return fmt.Errorf("GetRepositoryByName: %v", err)
}
// Push tags.
- if strings.HasPrefix(refName, "refs/tags/") {
- tagName := git.RefEndName(refName)
- tag, err := gitRepo.GetTag(tagName)
+ if strings.HasPrefix(opts.RefName, "refs/tags/") {
+ tag, err := gitRepo.GetTag(git.RefEndName(opts.RefName))
if err != nil {
- log.GitLogger.Fatal(4, "runUpdate.GetTag: %v", err)
+ return fmt.Errorf("gitRepo.GetTag: %v", err)
}
+ // When tagger isn't available, fall back to get committer email.
var actEmail string
if tag.Tagger != nil {
actEmail = tag.Tagger.Email
} else {
cmt, err := tag.Commit()
if err != nil {
- log.GitLogger.Fatal(4, "runUpdate.GetTag Commit: %v", err)
+ return fmt.Errorf("tag.Commit: %v", err)
}
actEmail = cmt.Committer.Email
}
commit := &PushCommits{}
-
- 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)
+ if err = CommitRepoAction(opts.PusherID, repoUser.Id, opts.PusherName, actEmail,
+ repo.ID, opts.RepoUserName, opts.RepoName, opts.RefName, commit, opts.OldCommitID, opts.NewCommitID); err != nil {
+ return fmt.Errorf("CommitRepoAction (tag): %v", err)
}
return err
}
- newCommit, err := gitRepo.GetCommit(newCommitID)
+ newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
if err != nil {
- return fmt.Errorf("runUpdate GetCommit of newCommitId: %v", err)
+ return fmt.Errorf("gitRepo.GetCommit: %v", err)
}
// Push new branch.
var l *list.List
- if isNew {
+ if isNewRef {
l, err = newCommit.CommitsBeforeLimit(10)
if err != nil {
- return fmt.Errorf("CommitsBefore: %v", err)
+ return fmt.Errorf("newCommit.CommitsBeforeLimit: %v", err)
}
} else {
- l, err = newCommit.CommitsBeforeUntil(oldCommitID)
+ l, err = newCommit.CommitsBeforeUntil(opts.OldCommitID)
if err != nil {
- return fmt.Errorf("CommitsBeforeUntil: %v", err)
+ return fmt.Errorf("newCommit.CommitsBeforeUntil: %v", err)
}
}
- if err != nil {
- return fmt.Errorf("runUpdate.Commit repoId: %v", err)
- }
-
- if err = CommitRepoAction(userID, user.Id, userName, user.Email,
- repo.ID, repoUserName, repoName, refName, ListToPushCommits(l), oldCommitID, newCommitID); err != nil {
- return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
+ if err = CommitRepoAction(opts.PusherID, repoUser.Id, opts.PusherName, repoUser.Email,
+ repo.ID, opts.RepoUserName, opts.RepoName, opts.RefName, ListToPushCommits(l),
+ opts.OldCommitID, opts.NewCommitID); err != nil {
+ return fmt.Errorf("CommitRepoAction (branch): %v", err)
}
return nil
}
diff --git a/models/user.go b/models/user.go
index 31ac1e22..7a881759 100644
--- a/models/user.go
+++ b/models/user.go
@@ -16,7 +16,6 @@ import (
_ "image/jpeg"
"image/png"
"os"
- "path"
"path/filepath"
"strings"
"time"
@@ -211,7 +210,7 @@ func (u *User) GenerateRandomAvatar() error {
if err != nil {
return fmt.Errorf("RandomImage: %v", err)
}
- if err = os.MkdirAll(path.Dir(u.CustomAvatarPath()), os.ModePerm); err != nil {
+ if err = os.MkdirAll(filepath.Dir(u.CustomAvatarPath()), os.ModePerm); err != nil {
return fmt.Errorf("MkdirAll: %v", err)
}
fw, err := os.Create(u.CustomAvatarPath())
@@ -248,8 +247,6 @@ func (u *User) RelAvatarLink() string {
}
return "/avatars/" + com.ToStr(u.Id)
- case setting.Service.EnableCacheAvatar:
- return "/avatar/" + u.Avatar
}
return setting.GravatarSource + u.Avatar
}
@@ -494,7 +491,7 @@ func CreateUser(u *User) (err error) {
u.LowerName = strings.ToLower(u.Name)
u.AvatarEmail = u.Email
- u.Avatar = avatar.HashEmail(u.AvatarEmail)
+ u.Avatar = base.HashEmail(u.AvatarEmail)
u.Rands = GetUserSalt()
u.Salt = GetUserSalt()
u.EncodePasswd()
@@ -599,11 +596,19 @@ func ChangeUserName(u *User, newUserName string) (err error) {
return ErrUserAlreadyExist{newUserName}
}
- err = ChangeUsernameInPullRequests(u.Name, newUserName)
- if err != nil {
+ if err = ChangeUsernameInPullRequests(u.Name, newUserName); err != nil {
return fmt.Errorf("ChangeUsernameInPullRequests: %v", err)
}
+ // Delete all local copies of repository wiki that user owns.
+ if err = x.Where("owner_id=?", u.Id).Iterate(new(Repository), func(idx int, bean interface{}) error {
+ repo := bean.(*Repository)
+ RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
+ return nil
+ }); err != nil {
+ return fmt.Errorf("Delete repository wiki local copy: %v", err)
+ }
+
return os.Rename(UserPath(u.Name), UserPath(newUserName))
}
@@ -621,7 +626,7 @@ func updateUser(e Engine, u *User) error {
if len(u.AvatarEmail) == 0 {
u.AvatarEmail = u.Email
}
- u.Avatar = avatar.HashEmail(u.AvatarEmail)
+ u.Avatar = base.HashEmail(u.AvatarEmail)
}
u.LowerName = strings.ToLower(u.Name)
diff --git a/models/webhook.go b/models/webhook.go
index 27ac75fe..bdfb62d8 100644
--- a/models/webhook.go
+++ b/models/webhook.go
@@ -398,6 +398,7 @@ func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) err
return nil
}
+ var payloader api.Payloader
for _, w := range ws {
switch event {
case HOOK_EVENT_CREATE:
@@ -410,14 +411,16 @@ func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) err
}
}
+ // Use separate objects so modifcations won't be made on payload on non-Gogs type hooks.
switch w.HookTaskType {
case SLACK:
- p, err = GetSlackPayload(p, event, w.Meta)
+ payloader, err = GetSlackPayload(p, event, w.Meta)
if err != nil {
return fmt.Errorf("GetSlackPayload: %v", err)
}
default:
p.SetSecret(w.Secret)
+ payloader = p
}
if err = CreateHookTask(&HookTask{
@@ -425,7 +428,7 @@ func PrepareWebhooks(repo *Repository, event HookEventType, p api.Payloader) err
HookID: w.ID,
Type: w.HookTaskType,
URL: w.URL,
- Payloader: p,
+ Payloader: payloader,
ContentType: w.ContentType,
EventType: HOOK_EVENT_PUSH,
IsSSL: w.IsSSL,