From 49737cf009a6a0fc119cf8a1a1593493c77c841a Mon Sep 17 00:00:00 2001
From: Earl Warren <contact@earl-warren.org>
Date: Wed, 9 Aug 2023 00:05:06 +0200
Subject: [PATCH] [UPGRADE] run sanity checks before the database is upgraded

(cherry picked from commit 69741e4e66932a9ac092089e7ba27399c55dcd1a)
(cherry picked from commit 2a3c7b09cbdfd62cca2619aaf37b6913a373d142)
(cherry picked from commit a1554c1168d897e8db4024d716a837c012bf74e9)
(cherry picked from commit edae2c6d2dda7f44e40ae88fba60a15f61b72232)
---
 models/migrations/migrations.go |  8 ++++++++
 services/forgejo/main_test.go   | 18 ++++++++++++++++++
 services/forgejo/sanity.go      | 25 +++++++++++++++++++++++++
 services/forgejo/sanity_test.go | 31 +++++++++++++++++++++++++++++++
 4 files changed, 82 insertions(+)
 create mode 100644 services/forgejo/main_test.go
 create mode 100644 services/forgejo/sanity.go
 create mode 100644 services/forgejo/sanity_test.go

diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 68b38044cb..b6e7afde5b 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -28,6 +28,7 @@ import (
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
+	forgejo_services "code.gitea.io/gitea/services/forgejo"
 
 	"xorm.io/xorm"
 	"xorm.io/xorm/names"
@@ -585,6 +586,7 @@ func Migrate(x *xorm.Engine) error {
 		return fmt.Errorf("sync: %w", err)
 	}
 
+	var previousVersion int64
 	currentVersion := &Version{ID: 1}
 	has, err := x.Get(currentVersion)
 	if err != nil {
@@ -598,6 +600,8 @@ func Migrate(x *xorm.Engine) error {
 		if _, err = x.InsertOne(currentVersion); err != nil {
 			return fmt.Errorf("insert: %w", err)
 		}
+	} else {
+		previousVersion = currentVersion.Version
 	}
 
 	v := currentVersion.Version
@@ -625,6 +629,10 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t
 		}
 	}
 
+	if err := forgejo_services.PreMigrationSanityChecks(x, previousVersion, setting.CfgProvider); err != nil {
+		return err
+	}
+
 	// Migrate
 	for i, m := range migrations[v-minDBVersion:] {
 		log.Info("Migration[%d]: %s", v+int64(i), m.Description())
diff --git a/services/forgejo/main_test.go b/services/forgejo/main_test.go
new file mode 100644
index 0000000000..d3d7d04766
--- /dev/null
+++ b/services/forgejo/main_test.go
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: MIT
+
+package forgejo
+
+import (
+	"path/filepath"
+	"testing"
+
+	"code.gitea.io/gitea/models/unittest"
+
+	_ "code.gitea.io/gitea/models"
+)
+
+func TestMain(m *testing.M) {
+	unittest.MainTest(m, &unittest.TestOptions{
+		GiteaRootPath: filepath.Join("..", ".."),
+	})
+}
diff --git a/services/forgejo/sanity.go b/services/forgejo/sanity.go
new file mode 100644
index 0000000000..0ca85c8406
--- /dev/null
+++ b/services/forgejo/sanity.go
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: MIT
+
+package forgejo
+
+import (
+	"code.gitea.io/gitea/models/db"
+	"code.gitea.io/gitea/modules/log"
+	"code.gitea.io/gitea/modules/setting"
+)
+
+var (
+	ForgejoV5DatabaseVersion = int64(260)
+	ForgejoV4DatabaseVersion = int64(244)
+)
+
+var logFatal = log.Fatal
+
+func fatal(err error) error {
+	logFatal("%v", err)
+	return err
+}
+
+func PreMigrationSanityChecks(e db.Engine, dbVersion int64, cfg setting.ConfigProvider) error {
+	return nil
+}
diff --git a/services/forgejo/sanity_test.go b/services/forgejo/sanity_test.go
new file mode 100644
index 0000000000..29ed3bbfff
--- /dev/null
+++ b/services/forgejo/sanity_test.go
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: MIT
+
+package forgejo
+
+import (
+	"os"
+	"path/filepath"
+	"testing"
+
+	"code.gitea.io/gitea/models/db"
+	"code.gitea.io/gitea/models/unittest"
+	"code.gitea.io/gitea/modules/setting"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestForgejo_PreMigrationSanityChecks(t *testing.T) {
+	assert.NoError(t, unittest.PrepareTestDatabase())
+	ctx := db.DefaultContext
+	e := db.GetEngine(ctx)
+
+	assert.NoError(t, PreMigrationSanityChecks(e, ForgejoV4DatabaseVersion, configFixture(t, "")))
+}
+
+func configFixture(t *testing.T, content string) setting.ConfigProvider {
+	config := filepath.Join(t.TempDir(), "app.ini")
+	assert.NoError(t, os.WriteFile(config, []byte(content), 0o777))
+	cfg, err := setting.NewConfigProviderFromFile(config)
+	assert.NoError(t, err)
+	return cfg
+}