* move database settings from models to setting * update docs * fix checkout pr * fix tests * fix lint * remove unsupported tidb options * correct wrong variable name * remove tidb totallytags/v1.21.12.1
| @@ -38,7 +38,7 @@ func initDB() error { | |||||
| func initDBDisableConsole(disableConsole bool) error { | func initDBDisableConsole(disableConsole bool) error { | ||||
| setting.NewContext() | setting.NewContext() | ||||
| models.LoadConfigs() | |||||
| setting.InitDBConfig() | |||||
| setting.NewXORMLogService(disableConsole) | setting.NewXORMLogService(disableConsole) | ||||
| if err := models.SetEngine(); err != nil { | if err := models.SetEngine(); err != nil { | ||||
| @@ -31,9 +31,9 @@ func runConvert(ctx *cli.Context) error { | |||||
| log.Trace("AppWorkPath: %s", setting.AppWorkPath) | log.Trace("AppWorkPath: %s", setting.AppWorkPath) | ||||
| log.Trace("Custom path: %s", setting.CustomPath) | log.Trace("Custom path: %s", setting.CustomPath) | ||||
| log.Trace("Log path: %s", setting.LogRootPath) | log.Trace("Log path: %s", setting.LogRootPath) | ||||
| models.LoadConfigs() | |||||
| setting.InitDBConfig() | |||||
| if models.DbCfg.Type != "mysql" { | |||||
| if !setting.Database.UseMySQL { | |||||
| fmt.Println("This command can only be used with a MySQL database") | fmt.Println("This command can only be used with a MySQL database") | ||||
| return nil | return nil | ||||
| } | } | ||||
| @@ -58,7 +58,6 @@ It can be used for backup and capture Gitea server image to send to maintainer`, | |||||
| func runDump(ctx *cli.Context) error { | func runDump(ctx *cli.Context) error { | ||||
| setting.NewContext() | setting.NewContext() | ||||
| setting.NewServices() // cannot access session settings otherwise | setting.NewServices() // cannot access session settings otherwise | ||||
| models.LoadConfigs() | |||||
| err := models.SetEngine() | err := models.SetEngine() | ||||
| if err != nil { | if err != nil { | ||||
| @@ -104,8 +103,8 @@ func runDump(ctx *cli.Context) error { | |||||
| } | } | ||||
| targetDBType := ctx.String("database") | targetDBType := ctx.String("database") | ||||
| if len(targetDBType) > 0 && targetDBType != models.DbCfg.Type { | |||||
| log.Printf("Dumping database %s => %s...", models.DbCfg.Type, targetDBType) | |||||
| if len(targetDBType) > 0 && targetDBType != setting.Database.Type { | |||||
| log.Printf("Dumping database %s => %s...", setting.Database.Type, targetDBType) | |||||
| } else { | } else { | ||||
| log.Printf("Dumping database...") | log.Printf("Dumping database...") | ||||
| } | } | ||||
| @@ -30,7 +30,7 @@ func runMigrate(ctx *cli.Context) error { | |||||
| log.Trace("AppWorkPath: %s", setting.AppWorkPath) | log.Trace("AppWorkPath: %s", setting.AppWorkPath) | ||||
| log.Trace("Custom path: %s", setting.CustomPath) | log.Trace("Custom path: %s", setting.CustomPath) | ||||
| log.Trace("Log path: %s", setting.LogRootPath) | log.Trace("Log path: %s", setting.LogRootPath) | ||||
| models.LoadConfigs() | |||||
| setting.InitDBConfig() | |||||
| if err := models.NewEngine(migrations.Migrate); err != nil { | if err := models.NewEngine(migrations.Migrate); err != nil { | ||||
| log.Fatal("Failed to initialize ORM engine: %v", err) | log.Fatal("Failed to initialize ORM engine: %v", err) | ||||
| @@ -79,16 +79,16 @@ func runPR() { | |||||
| setting.CheckLFSVersion() | setting.CheckLFSVersion() | ||||
| //models.LoadConfigs() | //models.LoadConfigs() | ||||
| /* | /* | ||||
| models.DbCfg.Type = "sqlite3" | |||||
| models.DbCfg.Path = ":memory:" | |||||
| models.DbCfg.Timeout = 500 | |||||
| setting.Database.Type = "sqlite3" | |||||
| setting.Database.Path = ":memory:" | |||||
| setting.Database.Timeout = 500 | |||||
| */ | */ | ||||
| db := setting.Cfg.Section("database") | db := setting.Cfg.Section("database") | ||||
| db.NewKey("DB_TYPE", "sqlite3") | db.NewKey("DB_TYPE", "sqlite3") | ||||
| db.NewKey("PATH", ":memory:") | db.NewKey("PATH", ":memory:") | ||||
| setting.LogSQL = true | |||||
| models.LoadConfigs() | |||||
| routers.NewServices() | routers.NewServices() | ||||
| setting.Database.LogSQL = true | |||||
| //x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared") | //x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared") | ||||
| var helper testfixtures.Helper = &testfixtures.SQLite{} | var helper testfixtures.Helper = &testfixtures.SQLite{} | ||||
| @@ -275,6 +275,10 @@ LOG_SQL = true | |||||
| DB_RETRIES = 10 | DB_RETRIES = 10 | ||||
| ; Backoff time per DB retry (time.Duration) | ; Backoff time per DB retry (time.Duration) | ||||
| DB_RETRY_BACKOFF = 3s | DB_RETRY_BACKOFF = 3s | ||||
| ; Max idle database connections on connnection pool, default is 0 | |||||
| MAX_IDLE_CONNS = 0 | |||||
| ; Database connection max life time, default is 3s | |||||
| CONN_MAX_LIFETIME = 3s | |||||
| [indexer] | [indexer] | ||||
| ; Issue indexer type, currently support: bleve or db, default is bleve | ; Issue indexer type, currently support: bleve or db, default is bleve | ||||
| @@ -166,6 +166,8 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`. | |||||
| - `LOG_SQL`: **true**: Log the executed SQL. | - `LOG_SQL`: **true**: Log the executed SQL. | ||||
| - `DB_RETRIES`: **10**: How many ORM init / DB connect attempts allowed. | - `DB_RETRIES`: **10**: How many ORM init / DB connect attempts allowed. | ||||
| - `DB_RETRY_BACKOFF`: **3s**: time.Duration to wait before trying another ORM init / DB connect attempt, if failure occured. | - `DB_RETRY_BACKOFF`: **3s**: time.Duration to wait before trying another ORM init / DB connect attempt, if failure occured. | ||||
| - `MAX_IDLE_CONNS` **0**: Max idle database connections on connnection pool, default is 0 | |||||
| - `CONN_MAX_LIFETIME` **3s**: Database connection max lifetime | |||||
| ## Indexer (`indexer`) | ## Indexer (`indexer`) | ||||
| @@ -82,6 +82,8 @@ menu: | |||||
| - `CHARSET`: **utf8**: 仅当数据库为 MySQL 时有效, 可以为 "utf8" 或 "utf8mb4"。注意:如果使用 "utf8mb4",你的 MySQL InnoDB 版本必须在 5.6 以上。 | - `CHARSET`: **utf8**: 仅当数据库为 MySQL 时有效, 可以为 "utf8" 或 "utf8mb4"。注意:如果使用 "utf8mb4",你的 MySQL InnoDB 版本必须在 5.6 以上。 | ||||
| - `PATH`: Tidb 或者 SQLite3 数据文件存放路径。 | - `PATH`: Tidb 或者 SQLite3 数据文件存放路径。 | ||||
| - `LOG_SQL`: **true**: 显示生成的SQL,默认为真。 | - `LOG_SQL`: **true**: 显示生成的SQL,默认为真。 | ||||
| - `MAX_IDLE_CONNS` **0**: 最大空闲数据库连接 | |||||
| - `CONN_MAX_LIFETIME` **3s**: 数据库连接最大存活时间 | |||||
| ## Indexer (`indexer`) | ## Indexer (`indexer`) | ||||
| @@ -59,13 +59,13 @@ func TestMain(m *testing.M) { | |||||
| routes.RegisterRoutes(mac) | routes.RegisterRoutes(mac) | ||||
| var helper testfixtures.Helper | var helper testfixtures.Helper | ||||
| if setting.UseMySQL { | |||||
| if setting.Database.UseMySQL { | |||||
| helper = &testfixtures.MySQL{} | helper = &testfixtures.MySQL{} | ||||
| } else if setting.UsePostgreSQL { | |||||
| } else if setting.Database.UsePostgreSQL { | |||||
| helper = &testfixtures.PostgreSQL{} | helper = &testfixtures.PostgreSQL{} | ||||
| } else if setting.UseSQLite3 { | |||||
| } else if setting.Database.UseSQLite3 { | |||||
| helper = &testfixtures.SQLite{} | helper = &testfixtures.SQLite{} | ||||
| } else if setting.UseMSSQL { | |||||
| } else if setting.Database.UseMSSQL { | |||||
| helper = &testfixtures.SQLServer{} | helper = &testfixtures.SQLServer{} | ||||
| } else { | } else { | ||||
| fmt.Println("Unsupported RDBMS for integration tests") | fmt.Println("Unsupported RDBMS for integration tests") | ||||
| @@ -121,12 +121,12 @@ func initIntegrationTest() { | |||||
| setting.SetCustomPathAndConf("", "", "") | setting.SetCustomPathAndConf("", "", "") | ||||
| setting.NewContext() | setting.NewContext() | ||||
| setting.CheckLFSVersion() | setting.CheckLFSVersion() | ||||
| models.LoadConfigs() | |||||
| setting.InitDBConfig() | |||||
| switch { | switch { | ||||
| case setting.UseMySQL: | |||||
| case setting.Database.UseMySQL: | |||||
| db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/", | db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/", | ||||
| models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host)) | |||||
| setting.Database.User, setting.Database.Passwd, setting.Database.Host)) | |||||
| defer db.Close() | defer db.Close() | ||||
| if err != nil { | if err != nil { | ||||
| log.Fatalf("sql.Open: %v", err) | log.Fatalf("sql.Open: %v", err) | ||||
| @@ -134,14 +134,14 @@ func initIntegrationTest() { | |||||
| if _, err = db.Exec("CREATE DATABASE IF NOT EXISTS testgitea"); err != nil { | if _, err = db.Exec("CREATE DATABASE IF NOT EXISTS testgitea"); err != nil { | ||||
| log.Fatalf("db.Exec: %v", err) | log.Fatalf("db.Exec: %v", err) | ||||
| } | } | ||||
| case setting.UsePostgreSQL: | |||||
| case setting.Database.UsePostgreSQL: | |||||
| db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s", | db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s", | ||||
| models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.SSLMode)) | |||||
| setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.SSLMode)) | |||||
| defer db.Close() | defer db.Close() | ||||
| if err != nil { | if err != nil { | ||||
| log.Fatalf("sql.Open: %v", err) | log.Fatalf("sql.Open: %v", err) | ||||
| } | } | ||||
| rows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", models.DbCfg.Name)) | |||||
| rows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", setting.Database.Name)) | |||||
| if err != nil { | if err != nil { | ||||
| log.Fatalf("db.Query: %v", err) | log.Fatalf("db.Query: %v", err) | ||||
| } | } | ||||
| @@ -153,10 +153,10 @@ func initIntegrationTest() { | |||||
| if _, err = db.Exec("CREATE DATABASE testgitea"); err != nil { | if _, err = db.Exec("CREATE DATABASE testgitea"); err != nil { | ||||
| log.Fatalf("db.Exec: %v", err) | log.Fatalf("db.Exec: %v", err) | ||||
| } | } | ||||
| case setting.UseMSSQL: | |||||
| host, port := models.ParseMSSQLHostPort(models.DbCfg.Host) | |||||
| case setting.Database.UseMSSQL: | |||||
| host, port := setting.ParseMSSQLHostPort(setting.Database.Host) | |||||
| db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", | db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", | ||||
| host, port, "master", models.DbCfg.User, models.DbCfg.Passwd)) | |||||
| host, port, "master", setting.Database.User, setting.Database.Passwd)) | |||||
| if err != nil { | if err != nil { | ||||
| log.Fatalf("sql.Open: %v", err) | log.Fatalf("sql.Open: %v", err) | ||||
| } | } | ||||
| @@ -39,7 +39,7 @@ func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| var lfsMetaObject *models.LFSMetaObject | var lfsMetaObject *models.LFSMetaObject | ||||
| if setting.UsePostgreSQL { | |||||
| if setting.Database.UsePostgreSQL { | |||||
| lfsMetaObject = &models.LFSMetaObject{ID: lfsID, Oid: oid, Size: int64(len(*content)), RepositoryID: repositoryID} | lfsMetaObject = &models.LFSMetaObject{ID: lfsID, Oid: oid, Size: int64(len(*content)), RepositoryID: repositoryID} | ||||
| } else { | } else { | ||||
| lfsMetaObject = &models.LFSMetaObject{Oid: oid, Size: int64(len(*content)), RepositoryID: repositoryID} | lfsMetaObject = &models.LFSMetaObject{Oid: oid, Size: int64(len(*content)), RepositoryID: repositoryID} | ||||
| @@ -54,7 +54,7 @@ func initMigrationTest(t *testing.T) { | |||||
| setting.NewContext() | setting.NewContext() | ||||
| setting.CheckLFSVersion() | setting.CheckLFSVersion() | ||||
| models.LoadConfigs() | |||||
| setting.InitDBConfig() | |||||
| setting.NewLogServices(true) | setting.NewLogServices(true) | ||||
| } | } | ||||
| @@ -64,7 +64,7 @@ func availableVersions() ([]string, error) { | |||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| defer migrationsDir.Close() | defer migrationsDir.Close() | ||||
| versionRE, err := regexp.Compile("gitea-v(?P<version>.+)\\." + regexp.QuoteMeta(models.DbCfg.Type) + "\\.sql.gz") | |||||
| versionRE, err := regexp.Compile("gitea-v(?P<version>.+)\\." + regexp.QuoteMeta(setting.Database.Type) + "\\.sql.gz") | |||||
| if err != nil { | if err != nil { | ||||
| return nil, err | return nil, err | ||||
| } | } | ||||
| @@ -85,7 +85,7 @@ func availableVersions() ([]string, error) { | |||||
| } | } | ||||
| func readSQLFromFile(version string) (string, error) { | func readSQLFromFile(version string) (string, error) { | ||||
| filename := fmt.Sprintf("integrations/migration-test/gitea-v%s.%s.sql.gz", version, models.DbCfg.Type) | |||||
| filename := fmt.Sprintf("integrations/migration-test/gitea-v%s.%s.sql.gz", version, setting.Database.Type) | |||||
| if _, err := os.Stat(filename); os.IsNotExist(err) { | if _, err := os.Stat(filename); os.IsNotExist(err) { | ||||
| return "", nil | return "", nil | ||||
| @@ -114,17 +114,17 @@ func restoreOldDB(t *testing.T, version string) bool { | |||||
| data, err := readSQLFromFile(version) | data, err := readSQLFromFile(version) | ||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| if len(data) == 0 { | if len(data) == 0 { | ||||
| integrations.Printf("No db found to restore for %s version: %s\n", models.DbCfg.Type, version) | |||||
| integrations.Printf("No db found to restore for %s version: %s\n", setting.Database.Type, version) | |||||
| return false | return false | ||||
| } | } | ||||
| switch { | switch { | ||||
| case setting.UseSQLite3: | |||||
| os.Remove(models.DbCfg.Path) | |||||
| err := os.MkdirAll(path.Dir(models.DbCfg.Path), os.ModePerm) | |||||
| case setting.Database.UseSQLite3: | |||||
| os.Remove(setting.Database.Path) | |||||
| err := os.MkdirAll(path.Dir(setting.Database.Path), os.ModePerm) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| db, err := sql.Open("sqlite3", fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", models.DbCfg.Path, models.DbCfg.Timeout)) | |||||
| db, err := sql.Open("sqlite3", fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", setting.Database.Path, setting.Database.Timeout)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| defer db.Close() | defer db.Close() | ||||
| @@ -132,20 +132,20 @@ func restoreOldDB(t *testing.T, version string) bool { | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| db.Close() | db.Close() | ||||
| case setting.UseMySQL: | |||||
| case setting.Database.UseMySQL: | |||||
| db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/", | db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/", | ||||
| models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host)) | |||||
| setting.Database.User, setting.Database.Passwd, setting.Database.Host)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| defer db.Close() | defer db.Close() | ||||
| _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", models.DbCfg.Name)) | |||||
| _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", setting.Database.Name)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", models.DbCfg.Name)) | |||||
| _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?multiStatements=true", | db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?multiStatements=true", | ||||
| models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.Name)) | |||||
| setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| defer db.Close() | defer db.Close() | ||||
| @@ -153,21 +153,21 @@ func restoreOldDB(t *testing.T, version string) bool { | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| db.Close() | db.Close() | ||||
| case setting.UsePostgreSQL: | |||||
| case setting.Database.UsePostgreSQL: | |||||
| db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s", | db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s", | ||||
| models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.SSLMode)) | |||||
| setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.SSLMode)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| defer db.Close() | defer db.Close() | ||||
| _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", models.DbCfg.Name)) | |||||
| _, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", setting.Database.Name)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", models.DbCfg.Name)) | |||||
| _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| db.Close() | db.Close() | ||||
| db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", | db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s", | ||||
| models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.Name, models.DbCfg.SSLMode)) | |||||
| setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.Name, setting.Database.SSLMode)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| defer db.Close() | defer db.Close() | ||||
| @@ -175,10 +175,10 @@ func restoreOldDB(t *testing.T, version string) bool { | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| db.Close() | db.Close() | ||||
| case setting.UseMSSQL: | |||||
| host, port := models.ParseMSSQLHostPort(models.DbCfg.Host) | |||||
| case setting.Database.UseMSSQL: | |||||
| host, port := setting.ParseMSSQLHostPort(setting.Database.Host) | |||||
| db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", | db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", | ||||
| host, port, "master", models.DbCfg.User, models.DbCfg.Passwd)) | |||||
| host, port, "master", setting.Database.User, setting.Database.Passwd)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| defer db.Close() | defer db.Close() | ||||
| @@ -191,7 +191,7 @@ func restoreOldDB(t *testing.T, version string) bool { | |||||
| dbname := statement[5 : len(statement)-1] | dbname := statement[5 : len(statement)-1] | ||||
| db.Close() | db.Close() | ||||
| db, err = sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", | db, err = sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", | ||||
| host, port, dbname, models.DbCfg.User, models.DbCfg.Passwd)) | |||||
| host, port, dbname, setting.Database.User, setting.Database.Passwd)) | |||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| defer db.Close() | defer db.Close() | ||||
| } | } | ||||
| @@ -210,7 +210,7 @@ func wrappedMigrate(x *xorm.Engine) error { | |||||
| func doMigrationTest(t *testing.T, version string) { | func doMigrationTest(t *testing.T, version string) { | ||||
| integrations.PrintCurrentTest(t) | integrations.PrintCurrentTest(t) | ||||
| integrations.Printf("Performing migration test for %s version: %s\n", models.DbCfg.Type, version) | |||||
| integrations.Printf("Performing migration test for %s version: %s\n", setting.Database.Type, version) | |||||
| if !restoreOldDB(t, version) { | if !restoreOldDB(t, version) { | ||||
| return | return | ||||
| } | } | ||||
| @@ -227,7 +227,7 @@ func doMigrationTest(t *testing.T, version string) { | |||||
| func TestMigrations(t *testing.T) { | func TestMigrations(t *testing.T) { | ||||
| initMigrationTest(t) | initMigrationTest(t) | ||||
| dialect := models.DbCfg.Type | |||||
| dialect := setting.Database.Type | |||||
| versions, err := availableVersions() | versions, err := availableVersions() | ||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| @@ -4,11 +4,15 @@ | |||||
| package models | package models | ||||
| import "fmt" | |||||
| import ( | |||||
| "fmt" | |||||
| "code.gitea.io/gitea/modules/setting" | |||||
| ) | |||||
| // ConvertUtf8ToUtf8mb4 converts database and tables from utf8 to utf8mb4 if it's mysql | // ConvertUtf8ToUtf8mb4 converts database and tables from utf8 to utf8mb4 if it's mysql | ||||
| func ConvertUtf8ToUtf8mb4() error { | func ConvertUtf8ToUtf8mb4() error { | ||||
| _, err := x.Exec(fmt.Sprintf("ALTER DATABASE `%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci", DbCfg.Name)) | |||||
| _, err := x.Exec(fmt.Sprintf("ALTER DATABASE `%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci", setting.Database.Name)) | |||||
| if err != nil { | if err != nil { | ||||
| return err | return err | ||||
| } | } | ||||
| @@ -296,7 +296,7 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin | |||||
| // TODO: This will not work if there are foreign keys | // TODO: This will not work if there are foreign keys | ||||
| switch { | switch { | ||||
| case setting.UseSQLite3: | |||||
| case setting.Database.UseSQLite3: | |||||
| // First drop the indexes on the columns | // First drop the indexes on the columns | ||||
| res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName)) | res, errIndex := sess.Query(fmt.Sprintf("PRAGMA index_list(`%s`)", tableName)) | ||||
| if errIndex != nil { | if errIndex != nil { | ||||
| @@ -372,7 +372,7 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin | |||||
| return err | return err | ||||
| } | } | ||||
| case setting.UsePostgreSQL: | |||||
| case setting.Database.UsePostgreSQL: | |||||
| cols := "" | cols := "" | ||||
| for _, col := range columnNames { | for _, col := range columnNames { | ||||
| if cols != "" { | if cols != "" { | ||||
| @@ -383,7 +383,7 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin | |||||
| if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil { | if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil { | ||||
| return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err) | return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err) | ||||
| } | } | ||||
| case setting.UseMySQL, setting.UseTiDB: | |||||
| case setting.Database.UseMySQL: | |||||
| // Drop indexes on columns first | // Drop indexes on columns first | ||||
| sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','")) | sql := fmt.Sprintf("SHOW INDEX FROM %s WHERE column_name IN ('%s')", tableName, strings.Join(columnNames, "','")) | ||||
| res, err := sess.Query(sql) | res, err := sess.Query(sql) | ||||
| @@ -409,7 +409,7 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin | |||||
| if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil { | if _, err := sess.Exec(fmt.Sprintf("ALTER TABLE `%s` %s", tableName, cols)); err != nil { | ||||
| return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err) | return fmt.Errorf("Drop table `%s` columns %v: %v", tableName, columnNames, err) | ||||
| } | } | ||||
| case setting.UseMSSQL: | |||||
| case setting.Database.UseMSSQL: | |||||
| cols := "" | cols := "" | ||||
| for _, col := range columnNames { | for _, col := range columnNames { | ||||
| if cols != "" { | if cols != "" { | ||||
| @@ -42,7 +42,7 @@ func generateAndMigrateGitHooks(x *xorm.Engine) (err error) { | |||||
| } | } | ||||
| ) | ) | ||||
| return x.Where("id > 0").BufferSize(setting.IterateBufferSize).Iterate(new(Repository), | |||||
| return x.Where("id > 0").BufferSize(setting.Database.IterateBufferSize).Iterate(new(Repository), | |||||
| func(idx int, bean interface{}) error { | func(idx int, bean interface{}) error { | ||||
| repo := bean.(*Repository) | repo := bean.(*Repository) | ||||
| user := new(User) | user := new(User) | ||||
| @@ -42,7 +42,7 @@ func generateAndMigrateWikiGitHooks(x *xorm.Engine) (err error) { | |||||
| } | } | ||||
| ) | ) | ||||
| return x.Where("id > 0").BufferSize(setting.IterateBufferSize).Iterate(new(Repository), | |||||
| return x.Where("id > 0").BufferSize(setting.Database.IterateBufferSize).Iterate(new(Repository), | |||||
| func(idx int, bean interface{}) error { | func(idx int, bean interface{}) error { | ||||
| repo := bean.(*Repository) | repo := bean.(*Repository) | ||||
| user := new(User) | user := new(User) | ||||
| @@ -36,7 +36,7 @@ func generateAndMigrateGitHookChains(x *xorm.Engine) (err error) { | |||||
| hookTpl = fmt.Sprintf("#!/usr/bin/env %s\ndata=$(cat)\nexitcodes=\"\"\nhookname=$(basename $0)\nGIT_DIR=${GIT_DIR:-$(dirname $0)}\n\nfor hook in ${GIT_DIR}/hooks/${hookname}.d/*; do\ntest -x \"${hook}\" || continue\necho \"${data}\" | \"${hook}\"\nexitcodes=\"${exitcodes} $?\"\ndone\n\nfor i in ${exitcodes}; do\n[ ${i} -eq 0 ] || exit ${i}\ndone\n", setting.ScriptType) | hookTpl = fmt.Sprintf("#!/usr/bin/env %s\ndata=$(cat)\nexitcodes=\"\"\nhookname=$(basename $0)\nGIT_DIR=${GIT_DIR:-$(dirname $0)}\n\nfor hook in ${GIT_DIR}/hooks/${hookname}.d/*; do\ntest -x \"${hook}\" || continue\necho \"${data}\" | \"${hook}\"\nexitcodes=\"${exitcodes} $?\"\ndone\n\nfor i in ${exitcodes}; do\n[ ${i} -eq 0 ] || exit ${i}\ndone\n", setting.ScriptType) | ||||
| ) | ) | ||||
| return x.Where("id > 0").BufferSize(setting.IterateBufferSize).Iterate(new(Repository), | |||||
| return x.Where("id > 0").BufferSize(setting.Database.IterateBufferSize).Iterate(new(Repository), | |||||
| func(idx int, bean interface{}) error { | func(idx int, bean interface{}) error { | ||||
| repo := bean.(*Repository) | repo := bean.(*Repository) | ||||
| user := new(User) | user := new(User) | ||||
| @@ -41,8 +41,6 @@ func convertIntervalToDuration(x *xorm.Engine) (err error) { | |||||
| _, err = sess.Exec("ALTER TABLE mirror MODIFY `interval` BIGINT") | _, err = sess.Exec("ALTER TABLE mirror MODIFY `interval` BIGINT") | ||||
| case "postgres": | case "postgres": | ||||
| _, err = sess.Exec("ALTER TABLE mirror ALTER COLUMN \"interval\" SET DATA TYPE bigint") | _, err = sess.Exec("ALTER TABLE mirror ALTER COLUMN \"interval\" SET DATA TYPE bigint") | ||||
| case "tidb": | |||||
| _, err = sess.Exec("ALTER TABLE mirror MODIFY `interval` BIGINT") | |||||
| case "mssql": | case "mssql": | ||||
| _, err = sess.Exec("ALTER TABLE mirror ALTER COLUMN \"interval\" BIGINT") | _, err = sess.Exec("ALTER TABLE mirror ALTER COLUMN \"interval\" BIGINT") | ||||
| case "sqlite3": | case "sqlite3": | ||||
| @@ -15,9 +15,9 @@ import ( | |||||
| func removeActionColumns(x *xorm.Engine) error { | func removeActionColumns(x *xorm.Engine) error { | ||||
| switch { | switch { | ||||
| case setting.UseSQLite3: | |||||
| case setting.Database.UseSQLite3: | |||||
| log.Warn("Unable to drop columns in SQLite") | log.Warn("Unable to drop columns in SQLite") | ||||
| case setting.UseMySQL, setting.UsePostgreSQL, setting.UseMSSQL, setting.UseTiDB: | |||||
| case setting.Database.UseMySQL, setting.Database.UsePostgreSQL, setting.Database.UseMSSQL: | |||||
| if _, err := x.Exec("ALTER TABLE action DROP COLUMN act_user_name"); err != nil { | if _, err := x.Exec("ALTER TABLE action DROP COLUMN act_user_name"); err != nil { | ||||
| return fmt.Errorf("DROP COLUMN act_user_name: %v", err) | return fmt.Errorf("DROP COLUMN act_user_name: %v", err) | ||||
| } else if _, err = x.Exec("ALTER TABLE action DROP COLUMN repo_user_name"); err != nil { | } else if _, err = x.Exec("ALTER TABLE action DROP COLUMN repo_user_name"); err != nil { | ||||
| @@ -13,9 +13,9 @@ import ( | |||||
| func removeIndexColumnFromRepoUnitTable(x *xorm.Engine) (err error) { | func removeIndexColumnFromRepoUnitTable(x *xorm.Engine) (err error) { | ||||
| switch { | switch { | ||||
| case setting.UseSQLite3: | |||||
| case setting.Database.UseSQLite3: | |||||
| log.Warn("Unable to drop columns in SQLite") | log.Warn("Unable to drop columns in SQLite") | ||||
| case setting.UseMySQL, setting.UsePostgreSQL, setting.UseMSSQL, setting.UseTiDB: | |||||
| case setting.Database.UseMySQL, setting.Database.UsePostgreSQL, setting.Database.UseMSSQL: | |||||
| if _, err := x.Exec("ALTER TABLE repo_unit DROP COLUMN `index`"); err != nil { | if _, err := x.Exec("ALTER TABLE repo_unit DROP COLUMN `index`"); err != nil { | ||||
| // Ignoring this error in case we run this migration second time (after migration reordering) | // Ignoring this error in case we run this migration second time (after migration reordering) | ||||
| log.Warn("DROP COLUMN index: %v", err) | log.Warn("DROP COLUMN index: %v", err) | ||||
| @@ -40,9 +40,9 @@ func migrateProtectedBranchStruct(x *xorm.Engine) error { | |||||
| } | } | ||||
| switch { | switch { | ||||
| case setting.UseSQLite3: | |||||
| case setting.Database.UseSQLite3: | |||||
| log.Warn("Unable to drop columns in SQLite") | log.Warn("Unable to drop columns in SQLite") | ||||
| case setting.UseMySQL, setting.UsePostgreSQL, setting.UseMSSQL, setting.UseTiDB: | |||||
| case setting.Database.UseMySQL, setting.Database.UsePostgreSQL, setting.Database.UseMSSQL: | |||||
| if _, err := x.Exec("ALTER TABLE protected_branch DROP COLUMN can_push"); err != nil { | if _, err := x.Exec("ALTER TABLE protected_branch DROP COLUMN can_push"); err != nil { | ||||
| // Ignoring this error in case we run this migration second time (after migration reordering) | // Ignoring this error in case we run this migration second time (after migration reordering) | ||||
| log.Warn("DROP COLUMN can_push (skipping): %v", err) | log.Warn("DROP COLUMN can_push (skipping): %v", err) | ||||
| @@ -80,7 +80,7 @@ func removeStaleWatches(x *xorm.Engine) error { | |||||
| } | } | ||||
| repoCache := make(map[int64]*Repository) | repoCache := make(map[int64]*Repository) | ||||
| err := sess.BufferSize(setting.IterateBufferSize).Iterate(new(Watch), | |||||
| err := sess.BufferSize(setting.Database.IterateBufferSize).Iterate(new(Watch), | |||||
| func(idx int, bean interface{}) error { | func(idx int, bean interface{}) error { | ||||
| watch := bean.(*Watch) | watch := bean.(*Watch) | ||||
| @@ -117,7 +117,7 @@ func removeStaleWatches(x *xorm.Engine) error { | |||||
| } | } | ||||
| repoCache = make(map[int64]*Repository) | repoCache = make(map[int64]*Repository) | ||||
| err = sess.BufferSize(setting.IterateBufferSize). | |||||
| err = sess.BufferSize(setting.Database.IterateBufferSize). | |||||
| Distinct("issue_watch.user_id", "issue.repo_id"). | Distinct("issue_watch.user_id", "issue.repo_id"). | ||||
| Join("INNER", "issue", "issue_watch.issue_id = issue.id"). | Join("INNER", "issue", "issue_watch.issue_id = issue.id"). | ||||
| Where("issue_watch.is_watching = ?", true). | Where("issue_watch.is_watching = ?", true). | ||||
| @@ -14,8 +14,6 @@ func changeU2FCounterType(x *xorm.Engine) error { | |||||
| var err error | var err error | ||||
| switch x.Dialect().DriverName() { | switch x.Dialect().DriverName() { | ||||
| case "tidb": | |||||
| fallthrough | |||||
| case "mysql": | case "mysql": | ||||
| _, err = x.Exec("ALTER TABLE `u2f_registration` MODIFY `counter` BIGINT") | _, err = x.Exec("ALTER TABLE `u2f_registration` MODIFY `counter` BIGINT") | ||||
| case "postgres": | case "postgres": | ||||
| @@ -9,12 +9,6 @@ import ( | |||||
| "database/sql" | "database/sql" | ||||
| "errors" | "errors" | ||||
| "fmt" | "fmt" | ||||
| "net/url" | |||||
| "os" | |||||
| "path" | |||||
| "path/filepath" | |||||
| "strings" | |||||
| "time" | |||||
| "code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
| @@ -52,24 +46,11 @@ type Engine interface { | |||||
| } | } | ||||
| var ( | var ( | ||||
| x *xorm.Engine | |||||
| supportedDatabases = []string{"mysql", "postgres", "mssql"} | |||||
| tables []interface{} | |||||
| x *xorm.Engine | |||||
| tables []interface{} | |||||
| // HasEngine specifies if we have a xorm.Engine | // HasEngine specifies if we have a xorm.Engine | ||||
| HasEngine bool | HasEngine bool | ||||
| // DbCfg holds the database settings | |||||
| DbCfg struct { | |||||
| Type, Host, Name, User, Passwd, Path, SSLMode, Charset string | |||||
| Timeout int | |||||
| } | |||||
| // EnableSQLite3 use SQLite3 | |||||
| EnableSQLite3 bool | |||||
| // EnableTiDB enable TiDB | |||||
| EnableTiDB bool | |||||
| ) | ) | ||||
| func init() { | func init() { | ||||
| @@ -139,120 +120,13 @@ func init() { | |||||
| } | } | ||||
| } | } | ||||
| // LoadConfigs loads the database settings | |||||
| func LoadConfigs() { | |||||
| sec := setting.Cfg.Section("database") | |||||
| DbCfg.Type = sec.Key("DB_TYPE").String() | |||||
| switch DbCfg.Type { | |||||
| case "sqlite3": | |||||
| setting.UseSQLite3 = true | |||||
| case "mysql": | |||||
| setting.UseMySQL = true | |||||
| case "postgres": | |||||
| setting.UsePostgreSQL = true | |||||
| case "tidb": | |||||
| setting.UseTiDB = true | |||||
| case "mssql": | |||||
| setting.UseMSSQL = true | |||||
| } | |||||
| DbCfg.Host = sec.Key("HOST").String() | |||||
| DbCfg.Name = sec.Key("NAME").String() | |||||
| DbCfg.User = sec.Key("USER").String() | |||||
| if len(DbCfg.Passwd) == 0 { | |||||
| DbCfg.Passwd = sec.Key("PASSWD").String() | |||||
| } | |||||
| DbCfg.SSLMode = sec.Key("SSL_MODE").MustString("disable") | |||||
| DbCfg.Charset = sec.Key("CHARSET").In("utf8", []string{"utf8", "utf8mb4"}) | |||||
| DbCfg.Path = sec.Key("PATH").MustString(filepath.Join(setting.AppDataPath, "gitea.db")) | |||||
| DbCfg.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500) | |||||
| } | |||||
| // parsePostgreSQLHostPort parses given input in various forms defined in | |||||
| // https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING | |||||
| // and returns proper host and port number. | |||||
| func parsePostgreSQLHostPort(info string) (string, string) { | |||||
| host, port := "127.0.0.1", "5432" | |||||
| if strings.Contains(info, ":") && !strings.HasSuffix(info, "]") { | |||||
| idx := strings.LastIndex(info, ":") | |||||
| host = info[:idx] | |||||
| port = info[idx+1:] | |||||
| } else if len(info) > 0 { | |||||
| host = info | |||||
| } | |||||
| return host, port | |||||
| } | |||||
| func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, dbsslMode string) (connStr string) { | |||||
| host, port := parsePostgreSQLHostPort(dbHost) | |||||
| if host[0] == '/' { // looks like a unix socket | |||||
| connStr = fmt.Sprintf("postgres://%s:%s@:%s/%s%ssslmode=%s&host=%s", | |||||
| url.PathEscape(dbUser), url.PathEscape(dbPasswd), port, dbName, dbParam, dbsslMode, host) | |||||
| } else { | |||||
| connStr = fmt.Sprintf("postgres://%s:%s@%s:%s/%s%ssslmode=%s", | |||||
| url.PathEscape(dbUser), url.PathEscape(dbPasswd), host, port, dbName, dbParam, dbsslMode) | |||||
| } | |||||
| return | |||||
| } | |||||
| // ParseMSSQLHostPort splits the host into host and port | |||||
| func ParseMSSQLHostPort(info string) (string, string) { | |||||
| host, port := "127.0.0.1", "1433" | |||||
| if strings.Contains(info, ":") { | |||||
| host = strings.Split(info, ":")[0] | |||||
| port = strings.Split(info, ":")[1] | |||||
| } else if strings.Contains(info, ",") { | |||||
| host = strings.Split(info, ",")[0] | |||||
| port = strings.TrimSpace(strings.Split(info, ",")[1]) | |||||
| } else if len(info) > 0 { | |||||
| host = info | |||||
| } | |||||
| return host, port | |||||
| } | |||||
| func getEngine() (*xorm.Engine, error) { | func getEngine() (*xorm.Engine, error) { | ||||
| connStr := "" | |||||
| var Param = "?" | |||||
| if strings.Contains(DbCfg.Name, Param) { | |||||
| Param = "&" | |||||
| } | |||||
| switch DbCfg.Type { | |||||
| case "mysql": | |||||
| connType := "tcp" | |||||
| if DbCfg.Host[0] == '/' { // looks like a unix socket | |||||
| connType = "unix" | |||||
| } | |||||
| tls := DbCfg.SSLMode | |||||
| if tls == "disable" { // allow (Postgres-inspired) default value to work in MySQL | |||||
| tls = "false" | |||||
| } | |||||
| connStr = fmt.Sprintf("%s:%s@%s(%s)/%s%scharset=%s&parseTime=true&tls=%s", | |||||
| DbCfg.User, DbCfg.Passwd, connType, DbCfg.Host, DbCfg.Name, Param, DbCfg.Charset, tls) | |||||
| case "postgres": | |||||
| connStr = getPostgreSQLConnectionString(DbCfg.Host, DbCfg.User, DbCfg.Passwd, DbCfg.Name, Param, DbCfg.SSLMode) | |||||
| case "mssql": | |||||
| host, port := ParseMSSQLHostPort(DbCfg.Host) | |||||
| connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, DbCfg.Name, DbCfg.User, DbCfg.Passwd) | |||||
| case "sqlite3": | |||||
| if !EnableSQLite3 { | |||||
| return nil, errors.New("this binary version does not build support for SQLite3") | |||||
| } | |||||
| if err := os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm); err != nil { | |||||
| return nil, fmt.Errorf("Failed to create directories: %v", err) | |||||
| } | |||||
| connStr = fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", DbCfg.Path, DbCfg.Timeout) | |||||
| case "tidb": | |||||
| if !EnableTiDB { | |||||
| return nil, errors.New("this binary version does not build support for TiDB") | |||||
| } | |||||
| if err := os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm); err != nil { | |||||
| return nil, fmt.Errorf("Failed to create directories: %v", err) | |||||
| } | |||||
| connStr = "goleveldb://" + DbCfg.Path | |||||
| default: | |||||
| return nil, fmt.Errorf("Unknown database type: %s", DbCfg.Type) | |||||
| connStr, err := setting.DBConnStr() | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | } | ||||
| return xorm.NewEngine(DbCfg.Type, connStr) | |||||
| return xorm.NewEngine(setting.Database.Type, connStr) | |||||
| } | } | ||||
| // NewTestEngine sets a new test xorm.Engine | // NewTestEngine sets a new test xorm.Engine | ||||
| @@ -280,11 +154,11 @@ func SetEngine() (err error) { | |||||
| x.SetMapper(core.GonicMapper{}) | x.SetMapper(core.GonicMapper{}) | ||||
| // WARNING: for serv command, MUST remove the output to os.stdout, | // WARNING: for serv command, MUST remove the output to os.stdout, | ||||
| // so use log file to instead print to stdout. | // so use log file to instead print to stdout. | ||||
| x.SetLogger(NewXORMLogger(setting.LogSQL)) | |||||
| x.ShowSQL(setting.LogSQL) | |||||
| if DbCfg.Type == "mysql" { | |||||
| x.SetMaxIdleConns(0) | |||||
| x.SetConnMaxLifetime(3 * time.Second) | |||||
| x.SetLogger(NewXORMLogger(setting.Database.LogSQL)) | |||||
| x.ShowSQL(setting.Database.LogSQL) | |||||
| if setting.Database.UseMySQL { | |||||
| x.SetMaxIdleConns(setting.Database.MaxIdleConns) | |||||
| x.SetConnMaxLifetime(setting.Database.ConnMaxLifetime) | |||||
| } | } | ||||
| return nil | return nil | ||||
| @@ -1,5 +1,4 @@ | |||||
| // Copyright 2016 The Gogs Authors. All rights reserved. | |||||
| // Copyright 2018 The Gitea Authors. All rights reserved. | |||||
| // Copyright 2019 The Gitea Authors. All rights reserved. | |||||
| // 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. | ||||
| @@ -11,99 +10,19 @@ import ( | |||||
| "path/filepath" | "path/filepath" | ||||
| "testing" | "testing" | ||||
| "code.gitea.io/gitea/modules/setting" | |||||
| "github.com/stretchr/testify/assert" | "github.com/stretchr/testify/assert" | ||||
| ) | ) | ||||
| func Test_parsePostgreSQLHostPort(t *testing.T) { | |||||
| tests := []struct { | |||||
| HostPort string | |||||
| Host string | |||||
| Port string | |||||
| }{ | |||||
| { | |||||
| HostPort: "127.0.0.1:1234", | |||||
| Host: "127.0.0.1", | |||||
| Port: "1234", | |||||
| }, | |||||
| { | |||||
| HostPort: "127.0.0.1", | |||||
| Host: "127.0.0.1", | |||||
| Port: "5432", | |||||
| }, | |||||
| { | |||||
| HostPort: "[::1]:1234", | |||||
| Host: "[::1]", | |||||
| Port: "1234", | |||||
| }, | |||||
| { | |||||
| HostPort: "[::1]", | |||||
| Host: "[::1]", | |||||
| Port: "5432", | |||||
| }, | |||||
| { | |||||
| HostPort: "/tmp/pg.sock:1234", | |||||
| Host: "/tmp/pg.sock", | |||||
| Port: "1234", | |||||
| }, | |||||
| { | |||||
| HostPort: "/tmp/pg.sock", | |||||
| Host: "/tmp/pg.sock", | |||||
| Port: "5432", | |||||
| }, | |||||
| } | |||||
| for _, test := range tests { | |||||
| host, port := parsePostgreSQLHostPort(test.HostPort) | |||||
| assert.Equal(t, test.Host, host) | |||||
| assert.Equal(t, test.Port, port) | |||||
| } | |||||
| } | |||||
| func Test_getPostgreSQLConnectionString(t *testing.T) { | |||||
| tests := []struct { | |||||
| Host string | |||||
| Port string | |||||
| User string | |||||
| Passwd string | |||||
| Name string | |||||
| Param string | |||||
| SSLMode string | |||||
| Output string | |||||
| }{ | |||||
| { | |||||
| Host: "/tmp/pg.sock", | |||||
| Port: "4321", | |||||
| User: "testuser", | |||||
| Passwd: "space space !#$%^^%^```-=?=", | |||||
| Name: "gitea", | |||||
| Param: "", | |||||
| SSLMode: "false", | |||||
| Output: "postgres://testuser:space%20space%20%21%23$%25%5E%5E%25%5E%60%60%60-=%3F=@:5432/giteasslmode=false&host=/tmp/pg.sock", | |||||
| }, | |||||
| { | |||||
| Host: "localhost", | |||||
| Port: "1234", | |||||
| User: "pgsqlusername", | |||||
| Passwd: "I love Gitea!", | |||||
| Name: "gitea", | |||||
| Param: "", | |||||
| SSLMode: "true", | |||||
| Output: "postgres://pgsqlusername:I%20love%20Gitea%21@localhost:5432/giteasslmode=true", | |||||
| }, | |||||
| } | |||||
| for _, test := range tests { | |||||
| connStr := getPostgreSQLConnectionString(test.Host, test.User, test.Passwd, test.Name, test.Param, test.SSLMode) | |||||
| assert.Equal(t, test.Output, connStr) | |||||
| } | |||||
| } | |||||
| func TestDumpDatabase(t *testing.T) { | func TestDumpDatabase(t *testing.T) { | ||||
| assert.NoError(t, PrepareTestDatabase()) | assert.NoError(t, PrepareTestDatabase()) | ||||
| dir, err := ioutil.TempDir(os.TempDir(), "dump") | dir, err := ioutil.TempDir(os.TempDir(), "dump") | ||||
| assert.NoError(t, err) | assert.NoError(t, err) | ||||
| for _, dbType := range supportedDatabases { | |||||
| for _, dbName := range setting.SupportedDatabases { | |||||
| dbType := setting.GetDBTypeByName(dbName) | |||||
| assert.NoError(t, DumpDatabase(filepath.Join(dir, dbType+".sql"), dbType)) | assert.NoError(t, DumpDatabase(filepath.Join(dir, dbType+".sql"), dbType)) | ||||
| } | } | ||||
| } | } | ||||
| @@ -2201,7 +2201,7 @@ func GitFsck() { | |||||
| log.Trace("Doing: GitFsck") | log.Trace("Doing: GitFsck") | ||||
| if err := x. | if err := x. | ||||
| Where("id>0 AND is_fsck_enabled=?", true).BufferSize(setting.IterateBufferSize). | |||||
| Where("id>0 AND is_fsck_enabled=?", true).BufferSize(setting.Database.IterateBufferSize). | |||||
| Iterate(new(Repository), | Iterate(new(Repository), | ||||
| func(idx int, bean interface{}) error { | func(idx int, bean interface{}) error { | ||||
| repo := bean.(*Repository) | repo := bean.(*Repository) | ||||
| @@ -2225,7 +2225,7 @@ func GitFsck() { | |||||
| func GitGcRepos() error { | func GitGcRepos() error { | ||||
| args := append([]string{"gc"}, setting.Git.GCArgs...) | args := append([]string{"gc"}, setting.Git.GCArgs...) | ||||
| return x. | return x. | ||||
| Where("id > 0").BufferSize(setting.IterateBufferSize). | |||||
| Where("id > 0").BufferSize(setting.Database.IterateBufferSize). | |||||
| Iterate(new(Repository), | Iterate(new(Repository), | ||||
| func(idx int, bean interface{}) error { | func(idx int, bean interface{}) error { | ||||
| repo := bean.(*Repository) | repo := bean.(*Repository) | ||||
| @@ -2568,7 +2568,7 @@ func (repo *Repository) generateRandomAvatar(e Engine) error { | |||||
| // RemoveRandomAvatars removes the randomly generated avatars that were created for repositories | // RemoveRandomAvatars removes the randomly generated avatars that were created for repositories | ||||
| func RemoveRandomAvatars() error { | func RemoveRandomAvatars() error { | ||||
| return x. | return x. | ||||
| Where("id > 0").BufferSize(setting.IterateBufferSize). | |||||
| Where("id > 0").BufferSize(setting.Database.IterateBufferSize). | |||||
| Iterate(new(Repository), | Iterate(new(Repository), | ||||
| func(idx int, bean interface{}) error { | func(idx int, bean interface{}) error { | ||||
| repository := bean.(*Repository) | repository := bean.(*Repository) | ||||
| @@ -49,7 +49,7 @@ func MainTest(m *testing.M, pathToGiteaRoot string) { | |||||
| setting.RunUser = "runuser" | setting.RunUser = "runuser" | ||||
| setting.SSH.Port = 3000 | setting.SSH.Port = 3000 | ||||
| setting.SSH.Domain = "try.gitea.io" | setting.SSH.Domain = "try.gitea.io" | ||||
| setting.UseSQLite3 = true | |||||
| setting.Database.UseSQLite3 = true | |||||
| setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos") | setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos") | ||||
| if err != nil { | if err != nil { | ||||
| fatalTestError("TempDir: %v\n", err) | fatalTestError("TempDir: %v\n", err) | ||||
| @@ -40,7 +40,6 @@ import ( | |||||
| "golang.org/x/crypto/scrypt" | "golang.org/x/crypto/scrypt" | ||||
| "golang.org/x/crypto/ssh" | "golang.org/x/crypto/ssh" | ||||
| "xorm.io/builder" | "xorm.io/builder" | ||||
| "xorm.io/core" | |||||
| ) | ) | ||||
| // UserType defines the user type | // UserType defines the user type | ||||
| @@ -1432,9 +1431,9 @@ func (opts *SearchUserOptions) toConds() builder.Cond { | |||||
| if opts.OwnerID > 0 { | if opts.OwnerID > 0 { | ||||
| var exprCond builder.Cond | var exprCond builder.Cond | ||||
| if DbCfg.Type == core.MYSQL { | |||||
| if setting.Database.UseMySQL { | |||||
| exprCond = builder.Expr("org_user.org_id = user.id") | exprCond = builder.Expr("org_user.org_id = user.id") | ||||
| } else if DbCfg.Type == core.MSSQL { | |||||
| } else if setting.Database.UseMSSQL { | |||||
| exprCond = builder.Expr("org_user.org_id = [user].id") | exprCond = builder.Expr("org_user.org_id = [user].id") | ||||
| } else { | } else { | ||||
| exprCond = builder.Expr("org_user.org_id = \"user\".id") | exprCond = builder.Expr("org_user.org_id = \"user\".id") | ||||
| @@ -21,13 +21,13 @@ func GetUserHeatmapDataByUser(user *User) ([]*UserHeatmapData, error) { | |||||
| var groupBy string | var groupBy string | ||||
| var groupByName = "timestamp" // We need this extra case because mssql doesn't allow grouping by alias | var groupByName = "timestamp" // We need this extra case because mssql doesn't allow grouping by alias | ||||
| switch { | switch { | ||||
| case setting.UseSQLite3: | |||||
| case setting.Database.UseSQLite3: | |||||
| groupBy = "strftime('%s', strftime('%Y-%m-%d', created_unix, 'unixepoch'))" | groupBy = "strftime('%s', strftime('%Y-%m-%d', created_unix, 'unixepoch'))" | ||||
| case setting.UseMySQL: | |||||
| case setting.Database.UseMySQL: | |||||
| groupBy = "UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(created_unix)))" | groupBy = "UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(created_unix)))" | ||||
| case setting.UsePostgreSQL: | |||||
| case setting.Database.UsePostgreSQL: | |||||
| groupBy = "extract(epoch from date_trunc('day', to_timestamp(created_unix)))" | groupBy = "extract(epoch from date_trunc('day', to_timestamp(created_unix)))" | ||||
| case setting.UseMSSQL: | |||||
| case setting.Database.UseMSSQL: | |||||
| groupBy = "datediff(SECOND, '19700101', dateadd(DAY, 0, datediff(day, 0, dateadd(s, created_unix, '19700101'))))" | groupBy = "datediff(SECOND, '19700101', dateadd(DAY, 0, datediff(day, 0, dateadd(s, created_unix, '19700101'))))" | ||||
| groupByName = groupBy | groupByName = groupBy | ||||
| } | } | ||||
| @@ -0,0 +1,171 @@ | |||||
| // Copyright 2019 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 setting | |||||
| import ( | |||||
| "errors" | |||||
| "fmt" | |||||
| "net/url" | |||||
| "os" | |||||
| "path" | |||||
| "path/filepath" | |||||
| "strings" | |||||
| "time" | |||||
| ) | |||||
| var ( | |||||
| // SupportedDatabases includes all supported databases type | |||||
| SupportedDatabases = []string{"MySQL", "PostgreSQL", "MSSQL"} | |||||
| dbTypes = map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "MSSQL": "mssql", "SQLite3": "sqlite3"} | |||||
| // EnableSQLite3 use SQLite3, set by build flag | |||||
| EnableSQLite3 bool | |||||
| // Database holds the database settings | |||||
| Database = struct { | |||||
| Type string | |||||
| Host string | |||||
| Name string | |||||
| User string | |||||
| Passwd string | |||||
| SSLMode string | |||||
| Path string | |||||
| LogSQL bool | |||||
| Charset string | |||||
| Timeout int // seconds | |||||
| UseSQLite3 bool | |||||
| UseMySQL bool | |||||
| UseMSSQL bool | |||||
| UsePostgreSQL bool | |||||
| DBConnectRetries int | |||||
| DBConnectBackoff time.Duration | |||||
| MaxIdleConns int | |||||
| ConnMaxLifetime time.Duration | |||||
| IterateBufferSize int | |||||
| }{ | |||||
| Timeout: 500, | |||||
| MaxIdleConns: 0, | |||||
| ConnMaxLifetime: 3 * time.Second, | |||||
| } | |||||
| ) | |||||
| // GetDBTypeByName returns the dataase type as it defined on XORM according the given name | |||||
| func GetDBTypeByName(name string) string { | |||||
| return dbTypes[name] | |||||
| } | |||||
| // InitDBConfig loads the database settings | |||||
| func InitDBConfig() { | |||||
| sec := Cfg.Section("database") | |||||
| Database.Type = sec.Key("DB_TYPE").String() | |||||
| switch Database.Type { | |||||
| case "sqlite3": | |||||
| Database.UseSQLite3 = true | |||||
| case "mysql": | |||||
| Database.UseMySQL = true | |||||
| case "postgres": | |||||
| Database.UsePostgreSQL = true | |||||
| case "mssql": | |||||
| Database.UseMSSQL = true | |||||
| } | |||||
| Database.Host = sec.Key("HOST").String() | |||||
| Database.Name = sec.Key("NAME").String() | |||||
| Database.User = sec.Key("USER").String() | |||||
| if len(Database.Passwd) == 0 { | |||||
| Database.Passwd = sec.Key("PASSWD").String() | |||||
| } | |||||
| Database.SSLMode = sec.Key("SSL_MODE").MustString("disable") | |||||
| Database.Charset = sec.Key("CHARSET").In("utf8", []string{"utf8", "utf8mb4"}) | |||||
| Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "gitea.db")) | |||||
| Database.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500) | |||||
| Database.MaxIdleConns = sec.Key("MAX_IDLE_CONNS").MustInt(0) | |||||
| Database.ConnMaxLifetime = sec.Key("CONN_MAX_LIFE_TIME").MustDuration(3 * time.Second) | |||||
| Database.IterateBufferSize = sec.Key("ITERATE_BUFFER_SIZE").MustInt(50) | |||||
| Database.LogSQL = sec.Key("LOG_SQL").MustBool(true) | |||||
| Database.DBConnectRetries = sec.Key("DB_RETRIES").MustInt(10) | |||||
| Database.DBConnectBackoff = sec.Key("DB_RETRY_BACKOFF").MustDuration(3 * time.Second) | |||||
| } | |||||
| // DBConnStr returns database connection string | |||||
| func DBConnStr() (string, error) { | |||||
| connStr := "" | |||||
| var Param = "?" | |||||
| if strings.Contains(Database.Name, Param) { | |||||
| Param = "&" | |||||
| } | |||||
| switch Database.Type { | |||||
| case "mysql": | |||||
| connType := "tcp" | |||||
| if Database.Host[0] == '/' { // looks like a unix socket | |||||
| connType = "unix" | |||||
| } | |||||
| tls := Database.SSLMode | |||||
| if tls == "disable" { // allow (Postgres-inspired) default value to work in MySQL | |||||
| tls = "false" | |||||
| } | |||||
| connStr = fmt.Sprintf("%s:%s@%s(%s)/%s%scharset=%s&parseTime=true&tls=%s", | |||||
| Database.User, Database.Passwd, connType, Database.Host, Database.Name, Param, Database.Charset, tls) | |||||
| case "postgres": | |||||
| connStr = getPostgreSQLConnectionString(Database.Host, Database.User, Database.Passwd, Database.Name, Param, Database.SSLMode) | |||||
| case "mssql": | |||||
| host, port := ParseMSSQLHostPort(Database.Host) | |||||
| connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, Database.Name, Database.User, Database.Passwd) | |||||
| case "sqlite3": | |||||
| if !EnableSQLite3 { | |||||
| return "", errors.New("this binary version does not build support for SQLite3") | |||||
| } | |||||
| if err := os.MkdirAll(path.Dir(Database.Path), os.ModePerm); err != nil { | |||||
| return "", fmt.Errorf("Failed to create directories: %v", err) | |||||
| } | |||||
| connStr = fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", Database.Path, Database.Timeout) | |||||
| default: | |||||
| return "", fmt.Errorf("Unknown database type: %s", Database.Type) | |||||
| } | |||||
| return connStr, nil | |||||
| } | |||||
| // parsePostgreSQLHostPort parses given input in various forms defined in | |||||
| // https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING | |||||
| // and returns proper host and port number. | |||||
| func parsePostgreSQLHostPort(info string) (string, string) { | |||||
| host, port := "127.0.0.1", "5432" | |||||
| if strings.Contains(info, ":") && !strings.HasSuffix(info, "]") { | |||||
| idx := strings.LastIndex(info, ":") | |||||
| host = info[:idx] | |||||
| port = info[idx+1:] | |||||
| } else if len(info) > 0 { | |||||
| host = info | |||||
| } | |||||
| return host, port | |||||
| } | |||||
| func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, dbsslMode string) (connStr string) { | |||||
| host, port := parsePostgreSQLHostPort(dbHost) | |||||
| if host[0] == '/' { // looks like a unix socket | |||||
| connStr = fmt.Sprintf("postgres://%s:%s@:%s/%s%ssslmode=%s&host=%s", | |||||
| url.PathEscape(dbUser), url.PathEscape(dbPasswd), port, dbName, dbParam, dbsslMode, host) | |||||
| } else { | |||||
| connStr = fmt.Sprintf("postgres://%s:%s@%s:%s/%s%ssslmode=%s", | |||||
| url.PathEscape(dbUser), url.PathEscape(dbPasswd), host, port, dbName, dbParam, dbsslMode) | |||||
| } | |||||
| return | |||||
| } | |||||
| // ParseMSSQLHostPort splits the host into host and port | |||||
| func ParseMSSQLHostPort(info string) (string, string) { | |||||
| host, port := "127.0.0.1", "1433" | |||||
| if strings.Contains(info, ":") { | |||||
| host = strings.Split(info, ":")[0] | |||||
| port = strings.Split(info, ":")[1] | |||||
| } else if strings.Contains(info, ",") { | |||||
| host = strings.Split(info, ",")[0] | |||||
| port = strings.TrimSpace(strings.Split(info, ",")[1]) | |||||
| } else if len(info) > 0 { | |||||
| host = info | |||||
| } | |||||
| return host, port | |||||
| } | |||||
| @@ -4,7 +4,7 @@ | |||||
| // 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 setting | |||||
| import ( | import ( | ||||
| _ "github.com/mattn/go-sqlite3" | _ "github.com/mattn/go-sqlite3" | ||||
| @@ -12,5 +12,5 @@ import ( | |||||
| func init() { | func init() { | ||||
| EnableSQLite3 = true | EnableSQLite3 = true | ||||
| supportedDatabases = append(supportedDatabases, "sqlite3") | |||||
| SupportedDatabases = append(SupportedDatabases, "SQLite3") | |||||
| } | } | ||||
| @@ -0,0 +1,94 @@ | |||||
| // Copyright 2019 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 setting | |||||
| import ( | |||||
| "testing" | |||||
| "github.com/stretchr/testify/assert" | |||||
| ) | |||||
| func Test_parsePostgreSQLHostPort(t *testing.T) { | |||||
| tests := []struct { | |||||
| HostPort string | |||||
| Host string | |||||
| Port string | |||||
| }{ | |||||
| { | |||||
| HostPort: "127.0.0.1:1234", | |||||
| Host: "127.0.0.1", | |||||
| Port: "1234", | |||||
| }, | |||||
| { | |||||
| HostPort: "127.0.0.1", | |||||
| Host: "127.0.0.1", | |||||
| Port: "5432", | |||||
| }, | |||||
| { | |||||
| HostPort: "[::1]:1234", | |||||
| Host: "[::1]", | |||||
| Port: "1234", | |||||
| }, | |||||
| { | |||||
| HostPort: "[::1]", | |||||
| Host: "[::1]", | |||||
| Port: "5432", | |||||
| }, | |||||
| { | |||||
| HostPort: "/tmp/pg.sock:1234", | |||||
| Host: "/tmp/pg.sock", | |||||
| Port: "1234", | |||||
| }, | |||||
| { | |||||
| HostPort: "/tmp/pg.sock", | |||||
| Host: "/tmp/pg.sock", | |||||
| Port: "5432", | |||||
| }, | |||||
| } | |||||
| for _, test := range tests { | |||||
| host, port := parsePostgreSQLHostPort(test.HostPort) | |||||
| assert.Equal(t, test.Host, host) | |||||
| assert.Equal(t, test.Port, port) | |||||
| } | |||||
| } | |||||
| func Test_getPostgreSQLConnectionString(t *testing.T) { | |||||
| tests := []struct { | |||||
| Host string | |||||
| Port string | |||||
| User string | |||||
| Passwd string | |||||
| Name string | |||||
| Param string | |||||
| SSLMode string | |||||
| Output string | |||||
| }{ | |||||
| { | |||||
| Host: "/tmp/pg.sock", | |||||
| Port: "4321", | |||||
| User: "testuser", | |||||
| Passwd: "space space !#$%^^%^```-=?=", | |||||
| Name: "gitea", | |||||
| Param: "", | |||||
| SSLMode: "false", | |||||
| Output: "postgres://testuser:space%20space%20%21%23$%25%5E%5E%25%5E%60%60%60-=%3F=@:5432/giteasslmode=false&host=/tmp/pg.sock", | |||||
| }, | |||||
| { | |||||
| Host: "localhost", | |||||
| Port: "1234", | |||||
| User: "pgsqlusername", | |||||
| Passwd: "I love Gitea!", | |||||
| Name: "gitea", | |||||
| Param: "", | |||||
| SSLMode: "true", | |||||
| Output: "postgres://pgsqlusername:I%20love%20Gitea%21@localhost:5432/giteasslmode=true", | |||||
| }, | |||||
| } | |||||
| for _, test := range tests { | |||||
| connStr := getPostgreSQLConnectionString(test.Host, test.User, test.Passwd, test.Name, test.Param, test.SSLMode) | |||||
| assert.Equal(t, test.Output, connStr) | |||||
| } | |||||
| } | |||||
| @@ -148,16 +148,6 @@ var ( | |||||
| DisableGitHooks bool | DisableGitHooks bool | ||||
| PasswordHashAlgo string | PasswordHashAlgo string | ||||
| // Database settings | |||||
| UseSQLite3 bool | |||||
| UseMySQL bool | |||||
| UseMSSQL bool | |||||
| UsePostgreSQL bool | |||||
| UseTiDB bool | |||||
| LogSQL bool | |||||
| DBConnectRetries int | |||||
| DBConnectBackoff time.Duration | |||||
| // UI settings | // UI settings | ||||
| UI = struct { | UI = struct { | ||||
| ExplorePagingNum int | ExplorePagingNum int | ||||
| @@ -348,16 +338,19 @@ var ( | |||||
| ShowFooterTemplateLoadTime bool | ShowFooterTemplateLoadTime bool | ||||
| // Global setting objects | // Global setting objects | ||||
| Cfg *ini.File | |||||
| CustomPath string // Custom directory path | |||||
| CustomConf string | |||||
| CustomPID string | |||||
| ProdMode bool | |||||
| RunUser string | |||||
| IsWindows bool | |||||
| HasRobotsTxt bool | |||||
| InternalToken string // internal access token | |||||
| IterateBufferSize int | |||||
| Cfg *ini.File | |||||
| CustomPath string // Custom directory path | |||||
| CustomConf string | |||||
| CustomPID string | |||||
| ProdMode bool | |||||
| RunUser string | |||||
| IsWindows bool | |||||
| HasRobotsTxt bool | |||||
| InternalToken string // internal access token | |||||
| // UILocation is the location on the UI, so that we can display the time on UI. | |||||
| // Currently only show the default time.Local, it could be added to app.ini after UI is ready | |||||
| UILocation = time.Local | |||||
| ) | ) | ||||
| // DateLang transforms standard language locale name to corresponding value in datetime plugin. | // DateLang transforms standard language locale name to corresponding value in datetime plugin. | ||||
| @@ -775,10 +768,6 @@ func NewContext() { | |||||
| CSRFCookieHTTPOnly = sec.Key("CSRF_COOKIE_HTTP_ONLY").MustBool(true) | CSRFCookieHTTPOnly = sec.Key("CSRF_COOKIE_HTTP_ONLY").MustBool(true) | ||||
| InternalToken = loadInternalToken(sec) | InternalToken = loadInternalToken(sec) | ||||
| IterateBufferSize = Cfg.Section("database").Key("ITERATE_BUFFER_SIZE").MustInt(50) | |||||
| LogSQL = Cfg.Section("database").Key("LOG_SQL").MustBool(true) | |||||
| DBConnectRetries = Cfg.Section("database").Key("DB_RETRIES").MustInt(10) | |||||
| DBConnectBackoff = Cfg.Section("database").Key("DB_RETRY_BACKOFF").MustDuration(3 * time.Second) | |||||
| sec = Cfg.Section("attachment") | sec = Cfg.Section("attachment") | ||||
| AttachmentPath = sec.Key("PATH").MustString(path.Join(AppDataPath, "attachments")) | AttachmentPath = sec.Key("PATH").MustString(path.Join(AppDataPath, "attachments")) | ||||
| @@ -1037,6 +1026,7 @@ func loadOrGenerateInternalToken(sec *ini.Section) string { | |||||
| // NewServices initializes the services | // NewServices initializes the services | ||||
| func NewServices() { | func NewServices() { | ||||
| InitDBConfig() | |||||
| newService() | newService() | ||||
| NewLogServices(false) | NewLogServices(false) | ||||
| newCacheService() | newCacheService() | ||||
| @@ -289,7 +289,7 @@ func Config(ctx *context.Context) { | |||||
| ctx.Data["LFS"] = setting.LFS | ctx.Data["LFS"] = setting.LFS | ||||
| ctx.Data["Service"] = setting.Service | ctx.Data["Service"] = setting.Service | ||||
| ctx.Data["DbCfg"] = models.DbCfg | |||||
| ctx.Data["DbCfg"] = setting.Database | |||||
| ctx.Data["Webhook"] = setting.Webhook | ctx.Data["Webhook"] = setting.Webhook | ||||
| ctx.Data["MailerEnabled"] = false | ctx.Data["MailerEnabled"] = false | ||||
| @@ -333,7 +333,7 @@ func Config(ctx *context.Context) { | |||||
| ctx.Data["AccessLogTemplate"] = setting.AccessLogTemplate | ctx.Data["AccessLogTemplate"] = setting.AccessLogTemplate | ||||
| ctx.Data["DisableRouterLog"] = setting.DisableRouterLog | ctx.Data["DisableRouterLog"] = setting.DisableRouterLog | ||||
| ctx.Data["EnableXORMLog"] = setting.EnableXORMLog | ctx.Data["EnableXORMLog"] = setting.EnableXORMLog | ||||
| ctx.Data["LogSQL"] = setting.LogSQL | |||||
| ctx.Data["LogSQL"] = setting.Database.LogSQL | |||||
| ctx.HTML(200, tplConfig) | ctx.HTML(200, tplConfig) | ||||
| } | } | ||||
| @@ -47,16 +47,16 @@ func NewServices() { | |||||
| // In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology | // In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology | ||||
| func initDBEngine() (err error) { | func initDBEngine() (err error) { | ||||
| log.Info("Beginning ORM engine initialization.") | log.Info("Beginning ORM engine initialization.") | ||||
| for i := 0; i < setting.DBConnectRetries; i++ { | |||||
| log.Info("ORM engine initialization attempt #%d/%d...", i+1, setting.DBConnectRetries) | |||||
| for i := 0; i < setting.Database.DBConnectRetries; i++ { | |||||
| log.Info("ORM engine initialization attempt #%d/%d...", i+1, setting.Database.DBConnectRetries) | |||||
| if err = models.NewEngine(migrations.Migrate); err == nil { | if err = models.NewEngine(migrations.Migrate); err == nil { | ||||
| break | break | ||||
| } else if i == setting.DBConnectRetries-1 { | |||||
| } else if i == setting.Database.DBConnectRetries-1 { | |||||
| return err | return err | ||||
| } | } | ||||
| log.Error("ORM engine initialization attempt #%d/%d failed. Error: %v", i+1, setting.DBConnectRetries, err) | |||||
| log.Info("Backing off for %d seconds", int64(setting.DBConnectBackoff/time.Second)) | |||||
| time.Sleep(setting.DBConnectBackoff) | |||||
| log.Error("ORM engine initialization attempt #%d/%d failed. Error: %v", i+1, setting.Database.DBConnectRetries, err) | |||||
| log.Info("Backing off for %d seconds", int64(setting.Database.DBConnectBackoff/time.Second)) | |||||
| time.Sleep(setting.Database.DBConnectBackoff) | |||||
| } | } | ||||
| models.HasEngine = true | models.HasEngine = true | ||||
| return nil | return nil | ||||
| @@ -73,7 +73,7 @@ func GlobalInit() { | |||||
| log.Trace("AppWorkPath: %s", setting.AppWorkPath) | log.Trace("AppWorkPath: %s", setting.AppWorkPath) | ||||
| log.Trace("Custom path: %s", setting.CustomPath) | log.Trace("Custom path: %s", setting.CustomPath) | ||||
| log.Trace("Log path: %s", setting.LogRootPath) | log.Trace("Log path: %s", setting.LogRootPath) | ||||
| models.LoadConfigs() | |||||
| NewServices() | NewServices() | ||||
| if setting.InstallLock { | if setting.InstallLock { | ||||
| @@ -102,12 +102,9 @@ func GlobalInit() { | |||||
| models.InitDeliverHooks() | models.InitDeliverHooks() | ||||
| models.InitTestPullRequests() | models.InitTestPullRequests() | ||||
| } | } | ||||
| if models.EnableSQLite3 { | |||||
| if setting.EnableSQLite3 { | |||||
| log.Info("SQLite3 Supported") | log.Info("SQLite3 Supported") | ||||
| } | } | ||||
| if models.EnableTiDB { | |||||
| log.Info("TiDB Supported") | |||||
| } | |||||
| checkRunMode() | checkRunMode() | ||||
| if setting.InstallLock && setting.SSH.StartBuiltinServer { | if setting.InstallLock && setting.SSH.StartBuiltinServer { | ||||
| @@ -40,11 +40,7 @@ func InstallInit(ctx *context.Context) { | |||||
| ctx.Data["Title"] = ctx.Tr("install.install") | ctx.Data["Title"] = ctx.Tr("install.install") | ||||
| ctx.Data["PageIsInstall"] = true | ctx.Data["PageIsInstall"] = true | ||||
| dbOpts := []string{"MySQL", "PostgreSQL", "MSSQL"} | |||||
| if models.EnableSQLite3 { | |||||
| dbOpts = append(dbOpts, "SQLite3") | |||||
| } | |||||
| ctx.Data["DbOptions"] = dbOpts | |||||
| ctx.Data["DbOptions"] = setting.SupportedDatabases | |||||
| } | } | ||||
| // Install render installation page | // Install render installation page | ||||
| @@ -52,21 +48,21 @@ func Install(ctx *context.Context) { | |||||
| form := auth.InstallForm{} | form := auth.InstallForm{} | ||||
| // Database settings | // Database settings | ||||
| form.DbHost = models.DbCfg.Host | |||||
| form.DbUser = models.DbCfg.User | |||||
| form.DbPasswd = models.DbCfg.Passwd | |||||
| form.DbName = models.DbCfg.Name | |||||
| form.DbPath = models.DbCfg.Path | |||||
| form.Charset = models.DbCfg.Charset | |||||
| form.DbHost = setting.Database.Host | |||||
| form.DbUser = setting.Database.User | |||||
| form.DbPasswd = setting.Database.Passwd | |||||
| form.DbName = setting.Database.Name | |||||
| form.DbPath = setting.Database.Path | |||||
| form.Charset = setting.Database.Charset | |||||
| ctx.Data["CurDbOption"] = "MySQL" | ctx.Data["CurDbOption"] = "MySQL" | ||||
| switch models.DbCfg.Type { | |||||
| switch setting.Database.Type { | |||||
| case "postgres": | case "postgres": | ||||
| ctx.Data["CurDbOption"] = "PostgreSQL" | ctx.Data["CurDbOption"] = "PostgreSQL" | ||||
| case "mssql": | case "mssql": | ||||
| ctx.Data["CurDbOption"] = "MSSQL" | ctx.Data["CurDbOption"] = "MSSQL" | ||||
| case "sqlite3": | case "sqlite3": | ||||
| if models.EnableSQLite3 { | |||||
| if setting.EnableSQLite3 { | |||||
| ctx.Data["CurDbOption"] = "SQLite3" | ctx.Data["CurDbOption"] = "SQLite3" | ||||
| } | } | ||||
| } | } | ||||
| @@ -144,18 +140,18 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) { | |||||
| // Pass basic check, now test configuration. | // Pass basic check, now test configuration. | ||||
| // Test database setting. | // Test database setting. | ||||
| dbTypes := map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "MSSQL": "mssql", "SQLite3": "sqlite3"} | |||||
| models.DbCfg.Type = dbTypes[form.DbType] | |||||
| models.DbCfg.Host = form.DbHost | |||||
| models.DbCfg.User = form.DbUser | |||||
| models.DbCfg.Passwd = form.DbPasswd | |||||
| models.DbCfg.Name = form.DbName | |||||
| models.DbCfg.SSLMode = form.SSLMode | |||||
| models.DbCfg.Charset = form.Charset | |||||
| models.DbCfg.Path = form.DbPath | |||||
| if (models.DbCfg.Type == "sqlite3") && | |||||
| len(models.DbCfg.Path) == 0 { | |||||
| setting.Database.Type = setting.GetDBTypeByName(form.DbType) | |||||
| setting.Database.Host = form.DbHost | |||||
| setting.Database.User = form.DbUser | |||||
| setting.Database.Passwd = form.DbPasswd | |||||
| setting.Database.Name = form.DbName | |||||
| setting.Database.SSLMode = form.SSLMode | |||||
| setting.Database.Charset = form.Charset | |||||
| setting.Database.Path = form.DbPath | |||||
| if (setting.Database.Type == "sqlite3") && | |||||
| len(setting.Database.Path) == 0 { | |||||
| ctx.Data["Err_DbPath"] = true | ctx.Data["Err_DbPath"] = true | ||||
| ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), tplInstall, &form) | ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), tplInstall, &form) | ||||
| return | return | ||||
| @@ -265,14 +261,14 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) { | |||||
| log.Error("Failed to load custom conf '%s': %v", setting.CustomConf, err) | log.Error("Failed to load custom conf '%s': %v", setting.CustomConf, err) | ||||
| } | } | ||||
| } | } | ||||
| cfg.Section("database").Key("DB_TYPE").SetValue(models.DbCfg.Type) | |||||
| cfg.Section("database").Key("HOST").SetValue(models.DbCfg.Host) | |||||
| cfg.Section("database").Key("NAME").SetValue(models.DbCfg.Name) | |||||
| cfg.Section("database").Key("USER").SetValue(models.DbCfg.User) | |||||
| cfg.Section("database").Key("PASSWD").SetValue(models.DbCfg.Passwd) | |||||
| cfg.Section("database").Key("SSL_MODE").SetValue(models.DbCfg.SSLMode) | |||||
| cfg.Section("database").Key("CHARSET").SetValue(models.DbCfg.Charset) | |||||
| cfg.Section("database").Key("PATH").SetValue(models.DbCfg.Path) | |||||
| cfg.Section("database").Key("DB_TYPE").SetValue(setting.Database.Type) | |||||
| cfg.Section("database").Key("HOST").SetValue(setting.Database.Host) | |||||
| cfg.Section("database").Key("NAME").SetValue(setting.Database.Name) | |||||
| cfg.Section("database").Key("USER").SetValue(setting.Database.User) | |||||
| cfg.Section("database").Key("PASSWD").SetValue(setting.Database.Passwd) | |||||
| cfg.Section("database").Key("SSL_MODE").SetValue(setting.Database.SSLMode) | |||||
| cfg.Section("database").Key("CHARSET").SetValue(setting.Database.Charset) | |||||
| cfg.Section("database").Key("PATH").SetValue(setting.Database.Path) | |||||
| cfg.Section("").Key("APP_NAME").SetValue(form.AppName) | cfg.Section("").Key("APP_NAME").SetValue(form.AppName) | ||||
| cfg.Section("repository").Key("ROOT").SetValue(form.RepoRootPath) | cfg.Section("repository").Key("ROOT").SetValue(form.RepoRootPath) | ||||