diff options
Diffstat (limited to 'models/repo_watch.go')
-rw-r--r-- | models/repo_watch.go | 141 |
1 files changed, 119 insertions, 22 deletions
diff --git a/models/repo_watch.go b/models/repo_watch.go index 53a34efdaf..cb864fb46d 100644 --- a/models/repo_watch.go +++ b/models/repo_watch.go @@ -4,42 +4,118 @@ package models -import "fmt" +import ( + "fmt" + + "code.gitea.io/gitea/modules/setting" +) + +// RepoWatchMode specifies what kind of watch the user has on a repository +type RepoWatchMode int8 + +const ( + // RepoWatchModeNone don't watch + RepoWatchModeNone RepoWatchMode = iota // 0 + // RepoWatchModeNormal watch repository (from other sources) + RepoWatchModeNormal // 1 + // RepoWatchModeDont explicit don't auto-watch + RepoWatchModeDont // 2 + // RepoWatchModeAuto watch repository (from AutoWatchOnChanges) + RepoWatchModeAuto // 3 +) // Watch is connection request for receiving repository notification. type Watch struct { - ID int64 `xorm:"pk autoincr"` - UserID int64 `xorm:"UNIQUE(watch)"` - RepoID int64 `xorm:"UNIQUE(watch)"` + ID int64 `xorm:"pk autoincr"` + UserID int64 `xorm:"UNIQUE(watch)"` + RepoID int64 `xorm:"UNIQUE(watch)"` + Mode RepoWatchMode `xorm:"SMALLINT NOT NULL DEFAULT 1"` } -func isWatching(e Engine, userID, repoID int64) bool { - has, _ := e.Get(&Watch{UserID: userID, RepoID: repoID}) - return has +// getWatch gets what kind of subscription a user has on a given repository; returns dummy record if none found +func getWatch(e Engine, userID, repoID int64) (Watch, error) { + watch := Watch{UserID: userID, RepoID: repoID} + has, err := e.Get(&watch) + if err != nil { + return watch, err + } + if !has { + watch.Mode = RepoWatchModeNone + } + return watch, nil +} + +// Decodes watchability of RepoWatchMode +func isWatchMode(mode RepoWatchMode) bool { + return mode != RepoWatchModeNone && mode != RepoWatchModeDont } // IsWatching checks if user has watched given repository. func IsWatching(userID, repoID int64) bool { - return isWatching(x, userID, repoID) + watch, err := getWatch(x, userID, repoID) + return err == nil && isWatchMode(watch.Mode) } -func watchRepo(e Engine, userID, repoID int64, watch bool) (err error) { - if watch { - if isWatching(e, userID, repoID) { - return nil - } - if _, err = e.Insert(&Watch{RepoID: repoID, UserID: userID}); err != nil { +func watchRepoMode(e Engine, watch Watch, mode RepoWatchMode) (err error) { + if watch.Mode == mode { + return nil + } + if mode == RepoWatchModeAuto && (watch.Mode == RepoWatchModeDont || isWatchMode(watch.Mode)) { + // Don't auto watch if already watching or deliberately not watching + return nil + } + + hadrec := watch.Mode != RepoWatchModeNone + needsrec := mode != RepoWatchModeNone + repodiff := 0 + + if isWatchMode(mode) && !isWatchMode(watch.Mode) { + repodiff = 1 + } else if !isWatchMode(mode) && isWatchMode(watch.Mode) { + repodiff = -1 + } + + watch.Mode = mode + + if !hadrec && needsrec { + watch.Mode = mode + if _, err = e.Insert(watch); err != nil { return err } - _, err = e.Exec("UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?", repoID) - } else { - if !isWatching(e, userID, repoID) { - return nil - } - if _, err = e.Delete(&Watch{0, userID, repoID}); err != nil { + } else if needsrec { + watch.Mode = mode + if _, err := e.ID(watch.ID).AllCols().Update(watch); err != nil { return err } - _, err = e.Exec("UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?", repoID) + } else if _, err = e.Delete(Watch{ID: watch.ID}); err != nil { + return err + } + if repodiff != 0 { + _, err = e.Exec("UPDATE `repository` SET num_watches = num_watches + ? WHERE id = ?", repodiff, watch.RepoID) + } + return err +} + +// WatchRepoMode watch repository in specific mode. +func WatchRepoMode(userID, repoID int64, mode RepoWatchMode) (err error) { + var watch Watch + if watch, err = getWatch(x, userID, repoID); err != nil { + return err + } + return watchRepoMode(x, watch, mode) +} + +func watchRepo(e Engine, userID, repoID int64, doWatch bool) (err error) { + var watch Watch + if watch, err = getWatch(e, userID, repoID); err != nil { + return err + } + if !doWatch && watch.Mode == RepoWatchModeAuto { + err = watchRepoMode(e, watch, RepoWatchModeDont) + } else if !doWatch { + err = watchRepoMode(e, watch, RepoWatchModeNone) + } else { + err = watchRepoMode(e, watch, RepoWatchModeNormal) } return err } @@ -52,6 +128,7 @@ func WatchRepo(userID, repoID int64, watch bool) (err error) { func getWatchers(e Engine, repoID int64) ([]*Watch, error) { watches := make([]*Watch, 0, 10) return watches, e.Where("`watch`.repo_id=?", repoID). + And("`watch`.mode<>?", RepoWatchModeDont). And("`user`.is_active=?", true). And("`user`.prohibit_login=?", false). Join("INNER", "`user`", "`user`.id = `watch`.user_id"). @@ -67,7 +144,8 @@ func GetWatchers(repoID int64) ([]*Watch, error) { func (repo *Repository) GetWatchers(page int) ([]*User, error) { users := make([]*User, 0, ItemsPerPage) sess := x.Where("watch.repo_id=?", repo.ID). - Join("LEFT", "watch", "`user`.id=`watch`.user_id") + Join("LEFT", "watch", "`user`.id=`watch`.user_id"). + And("`watch`.mode<>?", RepoWatchModeDont) if page > 0 { sess = sess.Limit(ItemsPerPage, (page-1)*ItemsPerPage) } @@ -137,3 +215,22 @@ func notifyWatchers(e Engine, act *Action) error { func NotifyWatchers(act *Action) error { return notifyWatchers(x, act) } + +func watchIfAuto(e Engine, userID, repoID int64, isWrite bool) error { + if !isWrite || !setting.Service.AutoWatchOnChanges { + return nil + } + watch, err := getWatch(e, userID, repoID) + if err != nil { + return err + } + if watch.Mode != RepoWatchModeNone { + return nil + } + return watchRepoMode(e, watch, RepoWatchModeAuto) +} + +// WatchIfAuto subscribes to repo if AutoWatchOnChanges is set +func WatchIfAuto(userID int64, repoID int64, isWrite bool) error { + return watchIfAuto(x, userID, repoID, isWrite) +} |