mirror of
				https://github.com/cloudreve/cloudreve.git
				synced 2025-11-01 00:57:15 +08:00 
			
		
		
		
	Feat: Decide whether to do database migration based on version.lock
				
					
				
			This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -13,3 +13,6 @@ | |||||||
|  |  | ||||||
| # Development enviroment | # Development enviroment | ||||||
| .idea/ | .idea/ | ||||||
|  |  | ||||||
|  | # Version control | ||||||
|  | version.lock | ||||||
| @ -1,3 +1,6 @@ | |||||||
|  | [System] | ||||||
|  | Debug = true | ||||||
|  |  | ||||||
| [Database] | [Database] | ||||||
| Type = mysql | Type = mysql | ||||||
| User = root | User = root | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.mod
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | |||||||
| module Cloudreve | module cloudreve | ||||||
|  |  | ||||||
| go 1.12 | go 1.12 | ||||||
|  |  | ||||||
| @ -10,6 +10,7 @@ require ( | |||||||
| 	github.com/go-playground/universal-translator v0.16.0 // indirect | 	github.com/go-playground/universal-translator v0.16.0 // indirect | ||||||
| 	github.com/jinzhu/gorm v1.9.11 | 	github.com/jinzhu/gorm v1.9.11 | ||||||
| 	github.com/leodido/go-urn v1.2.0 // indirect | 	github.com/leodido/go-urn v1.2.0 // indirect | ||||||
|  | 	github.com/mcuadros/go-version v0.0.0-20190830083331-035f6764e8d2 | ||||||
| 	github.com/pkg/errors v0.8.0 | 	github.com/pkg/errors v0.8.0 | ||||||
| 	github.com/stretchr/testify v1.4.0 | 	github.com/stretchr/testify v1.4.0 | ||||||
| 	gopkg.in/go-playground/validator.v8 v8.18.2 | 	gopkg.in/go-playground/validator.v8 v8.18.2 | ||||||
|  | |||||||
							
								
								
									
										13
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								main.go
									
									
									
									
									
								
							| @ -1,18 +1,23 @@ | |||||||
| package main | package main | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/models" | 	"cloudreve/models" | ||||||
| 	"Cloudreve/pkg/conf" | 	"cloudreve/pkg/conf" | ||||||
| 	"Cloudreve/routers" | 	"cloudreve/routers" | ||||||
|  | 	"github.com/gin-gonic/gin" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	conf.Init("conf/conf.ini") | 	conf.Init("conf/conf.ini") | ||||||
| 	model.Init() | 	model.Init() | ||||||
|  |  | ||||||
|  | 	// Debug 关闭时,切换为生产模式 | ||||||
|  | 	if !conf.SystemConfig.Debug { | ||||||
|  | 		gin.SetMode(gin.ReleaseMode) | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func main() { | func main() { | ||||||
|  |  | ||||||
| 	api := routers.InitRouter() | 	api := routers.InitRouter() | ||||||
|  |  | ||||||
| 	api.Run(":5000") | 	api.Run(":5000") | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| package model | package model | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/pkg/conf" | 	"cloudreve/pkg/conf" | ||||||
| 	"Cloudreve/pkg/util" | 	"cloudreve/pkg/util" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/jinzhu/gorm" | 	"github.com/jinzhu/gorm" | ||||||
| 	"time" | 	"time" | ||||||
| @ -15,7 +15,6 @@ var DB *gorm.DB | |||||||
|  |  | ||||||
| // Database 在中间件中初始化mysql链接 | // Database 在中间件中初始化mysql链接 | ||||||
| func Init() { | func Init() { | ||||||
| 	//TODO 从配置文件中读取 包括DEBUG模式 |  | ||||||
| 	util.Log().Info("初始化数据库连接\n") | 	util.Log().Info("初始化数据库连接\n") | ||||||
|  |  | ||||||
| 	var ( | 	var ( | ||||||
| @ -37,7 +36,11 @@ func Init() { | |||||||
| 		return conf.DatabaseConfig.TablePrefix + defaultTableName | 		return conf.DatabaseConfig.TablePrefix + defaultTableName | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// Debug 模式下,输出所有 SQL 日志 | ||||||
|  | 	if conf.SystemConfig.Debug { | ||||||
| 		db.LogMode(true) | 		db.LogMode(true) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	//db.SetLogger(util.Log()) | 	//db.SetLogger(util.Log()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		util.Log().Panic("连接数据库不成功", err) | 		util.Log().Panic("连接数据库不成功", err) | ||||||
|  | |||||||
| @ -1,14 +1,31 @@ | |||||||
| package model | package model | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/pkg/util" | 	"cloudreve/pkg/conf" | ||||||
|  | 	"cloudreve/pkg/util" | ||||||
| 	"github.com/jinzhu/gorm" | 	"github.com/jinzhu/gorm" | ||||||
|  | 	"github.com/mcuadros/go-version" | ||||||
|  | 	"io/ioutil" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| //执行数据迁移 | //执行数据迁移 | ||||||
| func migration() { | func migration() { | ||||||
|  | 	// 检查 version.lock 确认是否需要执行迁移 | ||||||
|  | 	// Debug 模式下一定会执行迁移 | ||||||
|  | 	if !conf.SystemConfig.Debug { | ||||||
|  | 		if util.Exists("version.lock") { | ||||||
|  | 			versionLock, _ := ioutil.ReadFile("version.lock") | ||||||
|  | 			if version.Compare(string(versionLock), conf.BackendVersion, "=") { | ||||||
|  | 				util.Log().Info("后端版本匹配,跳过数据库迁移") | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	util.Log().Info("开始进行数据库自动迁移...") | ||||||
|  |  | ||||||
| 	// 自动迁移模式 | 	// 自动迁移模式 | ||||||
| 	DB.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{}) | 	DB.Set("gorm:table_options", "ENGINE=InnoDB").AutoMigrate(&User{}, &Setting{}) | ||||||
|  |  | ||||||
| 	// 添加初始用户 | 	// 添加初始用户 | ||||||
| 	_, err := GetUser(1) | 	_, err := GetUser(1) | ||||||
| @ -29,4 +46,10 @@ func migration() { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// 迁移完毕后写入版本锁 version.lock | ||||||
|  | 	err = conf.WriteVersionLock() | ||||||
|  | 	if err != nil { | ||||||
|  | 		util.Log().Warning("无法写入版本控制锁 version.lock, ", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										26
									
								
								models/setting.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								models/setting.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | package model | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"github.com/jinzhu/gorm" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Setting 系统设置模型 | ||||||
|  | type Setting struct { | ||||||
|  | 	gorm.Model | ||||||
|  | 	Type  string `gorm:"not null"` | ||||||
|  | 	Name  string `gorm:"unique;not null;index:setting_key"` | ||||||
|  | 	Value string `gorm:"size:65535"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // GetSettingByName 用 Name 获取设置值 | ||||||
|  | func GetSettingByName(name string) (Setting, error) { | ||||||
|  | 	var setting Setting | ||||||
|  |  | ||||||
|  | 	// 优先尝试数据库中查找 | ||||||
|  | 	result := DB.Where("name = ?", name).First(&setting) | ||||||
|  | 	if result.Error == nil { | ||||||
|  | 		return setting, nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return setting, result.Error | ||||||
|  | } | ||||||
| @ -1,8 +1,8 @@ | |||||||
| package model | package model | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/pkg/serializer" | 	"cloudreve/pkg/serializer" | ||||||
| 	"Cloudreve/pkg/util" | 	"cloudreve/pkg/util" | ||||||
| 	"crypto/sha1" | 	"crypto/sha1" | ||||||
| 	"encoding/hex" | 	"encoding/hex" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
|  | |||||||
| @ -1,11 +1,11 @@ | |||||||
| package conf | package conf | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/pkg/util" | 	"cloudreve/pkg/util" | ||||||
| 	"github.com/go-ini/ini" | 	"github.com/go-ini/ini" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Database 数据库 | // database 数据库 | ||||||
| type database struct { | type database struct { | ||||||
| 	Type        string | 	Type        string | ||||||
| 	User        string | 	User        string | ||||||
| @ -19,6 +19,13 @@ var DatabaseConfig = &database{ | |||||||
| 	Type: "UNSET", | 	Type: "UNSET", | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // system 系统通用配置 | ||||||
|  | type system struct { | ||||||
|  | 	Debug bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var SystemConfig = &system{} | ||||||
|  |  | ||||||
| var cfg *ini.File | var cfg *ini.File | ||||||
|  |  | ||||||
| // Init 初始化配置文件 | // Init 初始化配置文件 | ||||||
| @ -30,9 +37,16 @@ func Init(path string) { | |||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		util.Log().Panic("无法解析配置文件 '%s': ", path, err) | 		util.Log().Panic("无法解析配置文件 '%s': ", path, err) | ||||||
| 	} | 	} | ||||||
| 	err = mapSection("Database", DatabaseConfig) |  | ||||||
|  | 	sections := map[string]interface{}{ | ||||||
|  | 		"Database": DatabaseConfig, | ||||||
|  | 		"System":   SystemConfig, | ||||||
|  | 	} | ||||||
|  | 	for sectionName, sectionStruct := range sections { | ||||||
|  | 		err = mapSection(sectionName, sectionStruct) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 		util.Log().Warning("配置文件 %s 分区解析失败: ", "Database", err) | 			util.Log().Warning("配置文件 %s 分区解析失败: ", sectionName, err) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -78,5 +78,4 @@ TablePrefix = v3_` | |||||||
| 	err = mapSection("Database", DatabaseConfig) | 	err = mapSection("Database", DatabaseConfig) | ||||||
| 	asserts.NoError(err) | 	asserts.NoError(err) | ||||||
|  |  | ||||||
| 	// TODO 类型不匹配测试 |  | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								pkg/conf/version.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								pkg/conf/version.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | package conf | ||||||
|  |  | ||||||
|  | import "io/ioutil" | ||||||
|  |  | ||||||
|  | const BackendVersion = string("3.0.0-b") | ||||||
|  |  | ||||||
|  | // WriteVersionLock 将当前版本信息写入 version.lock | ||||||
|  | func WriteVersionLock() error { | ||||||
|  | 	err := ioutil.WriteFile("version.lock", []byte(BackendVersion), 0644) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								pkg/util/io.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								pkg/util/io.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | package util | ||||||
|  |  | ||||||
|  | import "os" | ||||||
|  |  | ||||||
|  | // Exists reports whether the named file or directory exists. | ||||||
|  | func Exists(name string) bool { | ||||||
|  | 	if _, err := os.Stat(name); err != nil { | ||||||
|  | 		if os.IsNotExist(err) { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return true | ||||||
|  | } | ||||||
| @ -1,7 +1,7 @@ | |||||||
| package controllers | package controllers | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/pkg/serializer" | 	"cloudreve/pkg/serializer" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"gopkg.in/go-playground/validator.v8" | 	"gopkg.in/go-playground/validator.v8" | ||||||
| ) | ) | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package controllers | package controllers | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/pkg/serializer" | 	"cloudreve/pkg/serializer" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"github.com/stretchr/testify/assert" | 	"github.com/stretchr/testify/assert" | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package controllers | package controllers | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/pkg/serializer" | 	"cloudreve/pkg/serializer" | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package controllers | package controllers | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/service/user" | 	"cloudreve/service/user" | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package routers | package routers | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/routers/controllers" | 	"cloudreve/routers/controllers" | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| package service | package service | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"Cloudreve/pkg/serializer" | 	"cloudreve/pkg/serializer" | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 HFO4
					HFO4