mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Refactor update checker to use AppState (#17387)
We have the `AppState` module now, it can store app related data easily. We do not need to create separate tables for each feature. So the update checker can use `AppState` instead of a one-row dedicate table. And the code of update checker is moved from `models` to `modules`.
This commit is contained in:
		@@ -351,9 +351,11 @@ var migrations = []Migration{
 | 
				
			|||||||
	// v198 -> v199
 | 
						// v198 -> v199
 | 
				
			||||||
	NewMigration("Add issue content history table", addTableIssueContentHistory),
 | 
						NewMigration("Add issue content history table", addTableIssueContentHistory),
 | 
				
			||||||
	// v199 -> v200
 | 
						// v199 -> v200
 | 
				
			||||||
	NewMigration("Add remote version table", addRemoteVersionTable),
 | 
						NewMigration("No-op (remote version is using AppState now)", addRemoteVersionTableNoop),
 | 
				
			||||||
	// v200 -> v201
 | 
						// v200 -> v201
 | 
				
			||||||
	NewMigration("Add table app_state", addTableAppState),
 | 
						NewMigration("Add table app_state", addTableAppState),
 | 
				
			||||||
 | 
						// v201 -> v202
 | 
				
			||||||
 | 
						NewMigration("Drop table remote_version (if exists)", dropTableRemoteVersion),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetCurrentDBVersion returns the current db version
 | 
					// GetCurrentDBVersion returns the current db version
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,19 +5,10 @@
 | 
				
			|||||||
package migrations
 | 
					package migrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"xorm.io/xorm"
 | 
						"xorm.io/xorm"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func addRemoteVersionTable(x *xorm.Engine) error {
 | 
					func addRemoteVersionTableNoop(x *xorm.Engine) error {
 | 
				
			||||||
	type RemoteVersion struct {
 | 
						// we used to use a table `remote_version` to store information for updater, now we use `AppState`, so this migration task is a no-op now.
 | 
				
			||||||
		ID      int64  `xorm:"pk autoincr"`
 | 
					 | 
				
			||||||
		Version string `xorm:"VARCHAR(50)"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := x.Sync2(new(RemoteVersion)); err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("Sync2: %v", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								models/migrations/v201.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								models/migrations/v201.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					// Copyright 2021 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 (
 | 
				
			||||||
 | 
						"xorm.io/xorm"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func dropTableRemoteVersion(x *xorm.Engine) error {
 | 
				
			||||||
 | 
						// drop the orphaned table introduced in `v199`, now the update checker also uses AppState, do not need this table
 | 
				
			||||||
 | 
						_ = x.DropTables("remote_version")
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -11,6 +11,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
	repo_module "code.gitea.io/gitea/modules/repository"
 | 
						repo_module "code.gitea.io/gitea/modules/repository"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/updatechecker"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func registerDeleteInactiveUsers() {
 | 
					func registerDeleteInactiveUsers() {
 | 
				
			||||||
@@ -145,7 +146,7 @@ func registerUpdateGiteaChecker() {
 | 
				
			|||||||
		HTTPEndpoint: "https://dl.gitea.io/gitea/version.json",
 | 
							HTTPEndpoint: "https://dl.gitea.io/gitea/version.json",
 | 
				
			||||||
	}, func(ctx context.Context, _ *models.User, config Config) error {
 | 
						}, func(ctx context.Context, _ *models.User, config Config) error {
 | 
				
			||||||
		updateCheckerConfig := config.(*UpdateCheckerConfig)
 | 
							updateCheckerConfig := config.(*UpdateCheckerConfig)
 | 
				
			||||||
		return models.GiteaUpdateChecker(updateCheckerConfig.HTTPEndpoint)
 | 
							return updatechecker.GiteaUpdateChecker(updateCheckerConfig.HTTPEndpoint)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,29 +2,28 @@
 | 
				
			|||||||
// Use of this source code is governed by a MIT-style
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package models
 | 
					package updatechecker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models/db"
 | 
						"code.gitea.io/gitea/modules/appstate"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/proxy"
 | 
						"code.gitea.io/gitea/modules/proxy"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/hashicorp/go-version"
 | 
						"github.com/hashicorp/go-version"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RemoteVersion stores the remote version from the JSON endpoint
 | 
					// CheckerState stores the remote version from the JSON endpoint
 | 
				
			||||||
type RemoteVersion struct {
 | 
					type CheckerState struct {
 | 
				
			||||||
	ID      int64  `xorm:"pk autoincr"`
 | 
						LatestVersion string
 | 
				
			||||||
	Version string `xorm:"VARCHAR(50)"`
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					// Name returns the name of the state item for update checker
 | 
				
			||||||
	db.RegisterModel(new(RemoteVersion))
 | 
					func (r *CheckerState) Name() string {
 | 
				
			||||||
 | 
						return "update-checker"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GiteaUpdateChecker returns error when new version of Gitea is available
 | 
					// GiteaUpdateChecker returns error when new version of Gitea is available
 | 
				
			||||||
@@ -49,60 +48,33 @@ func GiteaUpdateChecker(httpEndpoint string) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type v struct {
 | 
						type respType struct {
 | 
				
			||||||
		Latest struct {
 | 
							Latest struct {
 | 
				
			||||||
			Version string `json:"version"`
 | 
								Version string `json:"version"`
 | 
				
			||||||
		} `json:"latest"`
 | 
							} `json:"latest"`
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ver := v{}
 | 
						respData := respType{}
 | 
				
			||||||
	err = json.Unmarshal(body, &ver)
 | 
						err = json.Unmarshal(body, &respData)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return UpdateRemoteVersion(ver.Latest.Version)
 | 
						return UpdateRemoteVersion(respData.Latest.Version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UpdateRemoteVersion updates the latest available version of Gitea
 | 
					// UpdateRemoteVersion updates the latest available version of Gitea
 | 
				
			||||||
func UpdateRemoteVersion(version string) (err error) {
 | 
					func UpdateRemoteVersion(version string) (err error) {
 | 
				
			||||||
	sess := db.NewSession(db.DefaultContext)
 | 
						return appstate.AppState.Set(&CheckerState{LatestVersion: version})
 | 
				
			||||||
	defer sess.Close()
 | 
					 | 
				
			||||||
	if err = sess.Begin(); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	currentVersion := &RemoteVersion{ID: 1}
 | 
					 | 
				
			||||||
	has, err := sess.Get(currentVersion)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("get: %v", err)
 | 
					 | 
				
			||||||
	} else if !has {
 | 
					 | 
				
			||||||
		currentVersion.ID = 1
 | 
					 | 
				
			||||||
		currentVersion.Version = version
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if _, err = sess.InsertOne(currentVersion); err != nil {
 | 
					 | 
				
			||||||
			return fmt.Errorf("insert: %v", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if _, err = sess.Update(&RemoteVersion{ID: 1, Version: version}); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return sess.Commit()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetRemoteVersion returns the current remote version (or currently installed verson if fail to fetch from DB)
 | 
					// GetRemoteVersion returns the current remote version (or currently installed verson if fail to fetch from DB)
 | 
				
			||||||
func GetRemoteVersion() string {
 | 
					func GetRemoteVersion() string {
 | 
				
			||||||
	e := db.GetEngine(db.DefaultContext)
 | 
						item := new(CheckerState)
 | 
				
			||||||
	v := &RemoteVersion{ID: 1}
 | 
						if err := appstate.AppState.Get(item); err != nil {
 | 
				
			||||||
	_, err := e.Get(&v)
 | 
							return ""
 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		// return current version if fail to fetch from DB
 | 
					 | 
				
			||||||
		return setting.AppVer
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return v.Version
 | 
						return item.LatestVersion
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetNeedUpdate returns true whether a newer version of Gitea is available
 | 
					// GetNeedUpdate returns true whether a newer version of Gitea is available
 | 
				
			||||||
@@ -112,7 +84,12 @@ func GetNeedUpdate() bool {
 | 
				
			|||||||
		// return false to fail silently
 | 
							// return false to fail silently
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	remoteVer, err := version.NewVersion(GetRemoteVersion())
 | 
						remoteVerStr := GetRemoteVersion()
 | 
				
			||||||
 | 
						if remoteVerStr == "" {
 | 
				
			||||||
 | 
							// no remote version is known
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						remoteVer, err := version.NewVersion(remoteVerStr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// return false to fail silently
 | 
							// return false to fail silently
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
@@ -26,6 +26,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/queue"
 | 
						"code.gitea.io/gitea/modules/queue"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/timeutil"
 | 
						"code.gitea.io/gitea/modules/timeutil"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/updatechecker"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/web"
 | 
						"code.gitea.io/gitea/modules/web"
 | 
				
			||||||
	"code.gitea.io/gitea/services/forms"
 | 
						"code.gitea.io/gitea/services/forms"
 | 
				
			||||||
	"code.gitea.io/gitea/services/mailer"
 | 
						"code.gitea.io/gitea/services/mailer"
 | 
				
			||||||
@@ -125,8 +126,8 @@ func Dashboard(ctx *context.Context) {
 | 
				
			|||||||
	ctx.Data["PageIsAdmin"] = true
 | 
						ctx.Data["PageIsAdmin"] = true
 | 
				
			||||||
	ctx.Data["PageIsAdminDashboard"] = true
 | 
						ctx.Data["PageIsAdminDashboard"] = true
 | 
				
			||||||
	ctx.Data["Stats"] = models.GetStatistic()
 | 
						ctx.Data["Stats"] = models.GetStatistic()
 | 
				
			||||||
	ctx.Data["NeedUpdate"] = models.GetNeedUpdate()
 | 
						ctx.Data["NeedUpdate"] = updatechecker.GetNeedUpdate()
 | 
				
			||||||
	ctx.Data["RemoteVersion"] = models.GetRemoteVersion()
 | 
						ctx.Data["RemoteVersion"] = updatechecker.GetRemoteVersion()
 | 
				
			||||||
	// FIXME: update periodically
 | 
						// FIXME: update periodically
 | 
				
			||||||
	updateSystemStatus()
 | 
						updateSystemStatus()
 | 
				
			||||||
	ctx.Data["SysStatus"] = sysStatus
 | 
						ctx.Data["SysStatus"] = sysStatus
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user