Migration fixes for gogs (0.11.66) to gitea (1.6.0) #5318 (#5341)
* Remove field from migration to support upgrades from older version
That will ensure the field does not get queried in the Select if it does
not exist yet:
```
[I] [SQL] SELECT "id", "repo_id", "index", "poster_id", "name", "content", "milestone_id", "priority", "assignee_id", "is_closed", "is_pull", "num_comments", "ref", "deadline_unix", "created_unix", "updated_unix
[...itea/routers/init.go:60 GlobalInit()] [E] Failed to initialize ORM engine: migrate: do migrate: pq: column "ref" does not exist
```
see #5318
* Skip remove stale watcher migration if not required
Otherwise the migration will fail if executed from a older database
version without multiple IssueWatch feature.
```
2018/11/11 23:51:14 [I] [SQL] SELECT DISTINCT "issue_watch"."user_id", "issue"."repo_id" FROM "issue_watch" INNER JOIN issue ON issue_watch.issue_id = issue.id WHERE (issue_watch.is_watching = $1) LIMIT 50 []int
[...itea/routers/init.go:60 GlobalInit()] [E] Failed to initialize ORM engine: migrate: do migrate: pq: relation "issue_watch" does not exist
```
see #5318
6 years ago Migration fixes for gogs (0.11.66) to gitea (1.6.0) #5318 (#5341)
* Remove field from migration to support upgrades from older version
That will ensure the field does not get queried in the Select if it does
not exist yet:
```
[I] [SQL] SELECT "id", "repo_id", "index", "poster_id", "name", "content", "milestone_id", "priority", "assignee_id", "is_closed", "is_pull", "num_comments", "ref", "deadline_unix", "created_unix", "updated_unix
[...itea/routers/init.go:60 GlobalInit()] [E] Failed to initialize ORM engine: migrate: do migrate: pq: column "ref" does not exist
```
see #5318
* Skip remove stale watcher migration if not required
Otherwise the migration will fail if executed from a older database
version without multiple IssueWatch feature.
```
2018/11/11 23:51:14 [I] [SQL] SELECT DISTINCT "issue_watch"."user_id", "issue"."repo_id" FROM "issue_watch" INNER JOIN issue ON issue_watch.issue_id = issue.id WHERE (issue_watch.is_watching = $1) LIMIT 50 []int
[...itea/routers/init.go:60 GlobalInit()] [E] Failed to initialize ORM engine: migrate: do migrate: pq: relation "issue_watch" does not exist
```
see #5318
6 years ago |
|
- // Copyright 2018 The Gitea Authors. All rights reserved.
- // Use of this source code is governed by a MIT-style
- // license that can be found in the LICENSE file.
-
- package migrations
-
- import (
- "fmt"
-
- "code.gitea.io/gitea/modules/setting"
-
- "xorm.io/xorm"
- )
-
- func removeStaleWatches(x *xorm.Engine) error {
- type Watch struct {
- ID int64
- UserID int64
- RepoID int64
- }
-
- type IssueWatch struct {
- ID int64
- UserID int64
- RepoID int64
- IsWatching bool
- }
-
- type Repository struct {
- ID int64
- IsPrivate bool
- OwnerID int64
- }
-
- type Access struct {
- UserID int64
- RepoID int64
- Mode int
- }
-
- const (
- // AccessModeNone no access
- AccessModeNone int = iota // 0
- // AccessModeRead read access
- AccessModeRead // 1
- )
-
- accessLevel := func(e *xorm.Session, userID int64, repo *Repository) (int, error) {
- mode := AccessModeNone
- if !repo.IsPrivate {
- mode = AccessModeRead
- }
-
- if userID == 0 {
- return mode, nil
- }
-
- if userID == repo.OwnerID {
- return 4, nil
- }
-
- a := &Access{UserID: userID, RepoID: repo.ID}
- if has, err := e.Get(a); !has || err != nil {
- return mode, err
- }
- return a.Mode, nil
- }
-
- sess := x.NewSession()
- defer sess.Close()
- if err := sess.Begin(); err != nil {
- return err
- }
-
- var issueWatch IssueWatch
- if exist, err := sess.IsTableExist(&issueWatch); err != nil {
- return fmt.Errorf("IsExist IssueWatch: %v", err)
- } else if !exist {
- return nil
- }
-
- repoCache := make(map[int64]*Repository)
- err := sess.BufferSize(setting.Database.IterateBufferSize).Iterate(new(Watch),
- func(idx int, bean interface{}) error {
- watch := bean.(*Watch)
-
- repo := repoCache[watch.RepoID]
- if repo == nil {
- repo = &Repository{
- ID: watch.RepoID,
- }
- if _, err := sess.Get(repo); err != nil {
- return err
- }
- repoCache[watch.RepoID] = repo
- }
-
- // Remove watches from now unaccessible repositories
- mode, err := accessLevel(sess, watch.UserID, repo)
- if err != nil {
- return err
- }
- has := AccessModeRead <= mode
- if has {
- return nil
- }
-
- if _, err = sess.Delete(&Watch{0, watch.UserID, repo.ID}); err != nil {
- return err
- }
- _, err = sess.Exec("UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?", repo.ID)
-
- return err
- })
- if err != nil {
- return err
- }
-
- repoCache = make(map[int64]*Repository)
- err = sess.BufferSize(setting.Database.IterateBufferSize).
- Distinct("issue_watch.user_id", "issue.repo_id").
- Join("INNER", "issue", "issue_watch.issue_id = issue.id").
- Where("issue_watch.is_watching = ?", true).
- Iterate(new(IssueWatch),
- func(idx int, bean interface{}) error {
- watch := bean.(*IssueWatch)
-
- repo := repoCache[watch.RepoID]
- if repo == nil {
- repo = &Repository{
- ID: watch.RepoID,
- }
- if _, err := sess.Get(repo); err != nil {
- return err
- }
- repoCache[watch.RepoID] = repo
- }
-
- // Remove issue watches from now unaccssible repositories
- mode, err := accessLevel(sess, watch.UserID, repo)
- if err != nil {
- return err
- }
- has := AccessModeRead <= mode
- if has {
- return nil
- }
-
- iw := &IssueWatch{
- IsWatching: false,
- }
-
- _, err = sess.
- Join("INNER", "issue", "`issue`.id = `issue_watch`.issue_id AND `issue`.repo_id = ?", watch.RepoID).
- Cols("is_watching", "updated_unix").
- Where("`issue_watch`.user_id = ?", watch.UserID).
- Update(iw)
-
- return err
-
- })
- if err != nil {
- return err
- }
-
- return sess.Commit()
- }
|