summaryrefslogtreecommitdiffstats
path: root/models/repo_watch.go
diff options
context:
space:
mode:
Diffstat (limited to 'models/repo_watch.go')
-rw-r--r--models/repo_watch.go141
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)
+}