summaryrefslogtreecommitdiffstats
path: root/models/forgejo_migrations
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-10-18 20:33:49 +0200
committerDaniel Baumann <daniel@debian.org>2024-10-18 20:33:49 +0200
commitdd136858f1ea40ad3c94191d647487fa4f31926c (patch)
tree58fec94a7b2a12510c9664b21793f1ed560c6518 /models/forgejo_migrations
parentInitial commit. (diff)
downloadforgejo-debian.tar.xz
forgejo-debian.zip
Adding upstream version 9.0.0.HEADupstream/9.0.0upstreamdebian
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to '')
-rw-r--r--models/forgejo_migrations/main_test.go14
-rw-r--r--models/forgejo_migrations/migrate.go192
-rw-r--r--models/forgejo_migrations/migrate_test.go39
-rw-r--r--models/forgejo_migrations/v13.go15
-rw-r--r--models/forgejo_migrations/v14.go43
-rw-r--r--models/forgejo_migrations/v15.go33
-rw-r--r--models/forgejo_migrations/v16.go17
-rw-r--r--models/forgejo_migrations/v17.go14
-rw-r--r--models/forgejo_migrations/v18.go18
-rw-r--r--models/forgejo_migrations/v19.go14
-rw-r--r--models/forgejo_migrations/v1_20/v1.go21
-rw-r--r--models/forgejo_migrations/v1_20/v2.go15
-rw-r--r--models/forgejo_migrations/v1_20/v3.go26
-rw-r--r--models/forgejo_migrations/v1_22/main_test.go14
-rw-r--r--models/forgejo_migrations/v1_22/v10.go17
-rw-r--r--models/forgejo_migrations/v1_22/v11.go19
-rw-r--r--models/forgejo_migrations/v1_22/v12.go18
-rw-r--r--models/forgejo_migrations/v1_22/v4.go17
-rw-r--r--models/forgejo_migrations/v1_22/v5.go22
-rw-r--r--models/forgejo_migrations/v1_22/v6.go24
-rw-r--r--models/forgejo_migrations/v1_22/v7.go17
-rw-r--r--models/forgejo_migrations/v1_22/v8.go51
-rw-r--r--models/forgejo_migrations/v1_22/v8_test.go35
-rw-r--r--models/forgejo_migrations/v1_22/v9.go15
-rw-r--r--models/forgejo_migrations/v20.go52
-rw-r--r--models/forgejo_migrations/v21.go16
-rw-r--r--models/forgejo_migrations/v22.go17
27 files changed, 795 insertions, 0 deletions
diff --git a/models/forgejo_migrations/main_test.go b/models/forgejo_migrations/main_test.go
new file mode 100644
index 0000000..2297f74
--- /dev/null
+++ b/models/forgejo_migrations/main_test.go
@@ -0,0 +1,14 @@
+// Copyright 2023 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import (
+ "testing"
+
+ migration_tests "code.gitea.io/gitea/models/migrations/test"
+)
+
+func TestMain(m *testing.M) {
+ migration_tests.MainTest(m)
+}
diff --git a/models/forgejo_migrations/migrate.go b/models/forgejo_migrations/migrate.go
new file mode 100644
index 0000000..cca83d6
--- /dev/null
+++ b/models/forgejo_migrations/migrate.go
@@ -0,0 +1,192 @@
+// Copyright 2023 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "code.gitea.io/gitea/models/forgejo/semver"
+ forgejo_v1_20 "code.gitea.io/gitea/models/forgejo_migrations/v1_20"
+ forgejo_v1_22 "code.gitea.io/gitea/models/forgejo_migrations/v1_22"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+
+ "xorm.io/xorm"
+ "xorm.io/xorm/names"
+)
+
+// ForgejoVersion describes the Forgejo version table. Should have only one row with id = 1.
+type ForgejoVersion struct {
+ ID int64 `xorm:"pk autoincr"`
+ Version int64
+}
+
+type Migration struct {
+ description string
+ migrate func(*xorm.Engine) error
+}
+
+// NewMigration creates a new migration.
+func NewMigration(desc string, fn func(*xorm.Engine) error) *Migration {
+ return &Migration{desc, fn}
+}
+
+// This is a sequence of additional Forgejo migrations.
+// Add new migrations to the bottom of the list.
+var migrations = []*Migration{
+ // v0 -> v1
+ NewMigration("Create the `forgejo_blocked_user` table", forgejo_v1_20.AddForgejoBlockedUser),
+ // v1 -> v2
+ NewMigration("Create the `forgejo_sem_ver` table", forgejo_v1_20.CreateSemVerTable),
+ // v2 -> v3
+ NewMigration("Create the `forgejo_auth_token` table", forgejo_v1_20.CreateAuthorizationTokenTable),
+ // v3 -> v4
+ NewMigration("Add the `default_permissions` column to the `repo_unit` table", forgejo_v1_22.AddDefaultPermissionsToRepoUnit),
+ // v4 -> v5
+ NewMigration("Create the `forgejo_repo_flag` table", forgejo_v1_22.CreateRepoFlagTable),
+ // v5 -> v6
+ NewMigration("Add the `wiki_branch` column to the `repository` table", forgejo_v1_22.AddWikiBranchToRepository),
+ // v6 -> v7
+ NewMigration("Add the `enable_repo_unit_hints` column to the `user` table", forgejo_v1_22.AddUserRepoUnitHintsSetting),
+ // v7 -> v8
+ NewMigration("Modify the `release`.`note` content to remove SSH signatures", forgejo_v1_22.RemoveSSHSignaturesFromReleaseNotes),
+ // v8 -> v9
+ NewMigration("Add the `apply_to_admins` column to the `protected_branch` table", forgejo_v1_22.AddApplyToAdminsSetting),
+ // v9 -> v10
+ NewMigration("Add pronouns to user", forgejo_v1_22.AddPronounsToUser),
+ // v11 -> v12
+ NewMigration("Add the `created` column to the `issue` table", forgejo_v1_22.AddCreatedToIssue),
+ // v12 -> v13
+ NewMigration("Add repo_archive_download_count table", forgejo_v1_22.AddRepoArchiveDownloadCount),
+ // v13 -> v14
+ NewMigration("Add `hide_archive_links` column to `release` table", AddHideArchiveLinksToRelease),
+ // v14 -> v15
+ NewMigration("Remove Gitea-specific columns from the repository and badge tables", RemoveGiteaSpecificColumnsFromRepositoryAndBadge),
+ // v15 -> v16
+ NewMigration("Create the `federation_host` table", CreateFederationHostTable),
+ // v16 -> v17
+ NewMigration("Create the `federated_user` table", CreateFederatedUserTable),
+ // v17 -> v18
+ NewMigration("Add `normalized_federated_uri` column to `user` table", AddNormalizedFederatedURIToUser),
+ // v18 -> v19
+ NewMigration("Create the `following_repo` table", CreateFollowingRepoTable),
+ // v19 -> v20
+ NewMigration("Add external_url to attachment table", AddExternalURLColumnToAttachmentTable),
+ // v20 -> v21
+ NewMigration("Creating Quota-related tables", CreateQuotaTables),
+ // v21 -> v22
+ NewMigration("Add SSH keypair to `pull_mirror` table", AddSSHKeypairToPushMirror),
+ // v22 -> v23
+ NewMigration("Add `legacy` to `web_authn_credential` table", AddLegacyToWebAuthnCredential),
+}
+
+// GetCurrentDBVersion returns the current Forgejo database version.
+func GetCurrentDBVersion(x *xorm.Engine) (int64, error) {
+ if err := x.Sync(new(ForgejoVersion)); err != nil {
+ return -1, fmt.Errorf("sync: %w", err)
+ }
+
+ currentVersion := &ForgejoVersion{ID: 1}
+ has, err := x.Get(currentVersion)
+ if err != nil {
+ return -1, fmt.Errorf("get: %w", err)
+ }
+ if !has {
+ return -1, nil
+ }
+ return currentVersion.Version, nil
+}
+
+// ExpectedVersion returns the expected Forgejo database version.
+func ExpectedVersion() int64 {
+ return int64(len(migrations))
+}
+
+// EnsureUpToDate will check if the Forgejo database is at the correct version.
+func EnsureUpToDate(x *xorm.Engine) error {
+ currentDB, err := GetCurrentDBVersion(x)
+ if err != nil {
+ return err
+ }
+
+ if currentDB < 0 {
+ return fmt.Errorf("database has not been initialized")
+ }
+
+ expected := ExpectedVersion()
+
+ if currentDB != expected {
+ return fmt.Errorf(`current Forgejo database version %d is not equal to the expected version %d. Please run "forgejo [--config /path/to/app.ini] migrate" to update the database version`, currentDB, expected)
+ }
+
+ return nil
+}
+
+// Migrate Forgejo database to current version.
+func Migrate(x *xorm.Engine) error {
+ // Set a new clean the default mapper to GonicMapper as that is the default for .
+ x.SetMapper(names.GonicMapper{})
+ if err := x.Sync(new(ForgejoVersion)); err != nil {
+ return fmt.Errorf("sync: %w", err)
+ }
+
+ currentVersion := &ForgejoVersion{ID: 1}
+ has, err := x.Get(currentVersion)
+ if err != nil {
+ return fmt.Errorf("get: %w", err)
+ } else if !has {
+ // If the version record does not exist we think
+ // it is a fresh installation and we can skip all migrations.
+ currentVersion.ID = 0
+ currentVersion.Version = ExpectedVersion()
+
+ if _, err = x.InsertOne(currentVersion); err != nil {
+ return fmt.Errorf("insert: %w", err)
+ }
+ }
+
+ v := currentVersion.Version
+
+ // Downgrading Forgejo's database version not supported
+ if v > ExpectedVersion() {
+ msg := fmt.Sprintf("Your Forgejo database (migration version: %d) is for a newer version of Forgejo, you cannot use the newer database for this old Forgejo release (%d).", v, ExpectedVersion())
+ msg += "\nForgejo will exit to keep your database safe and unchanged. Please use the correct Forgejo release, do not change the migration version manually (incorrect manual operation may cause data loss)."
+ if !setting.IsProd {
+ msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE forgejo_version SET version=%d WHERE id=1;", ExpectedVersion())
+ }
+ _, _ = fmt.Fprintln(os.Stderr, msg)
+ log.Fatal(msg)
+ return nil
+ }
+
+ // Some migration tasks depend on the git command
+ if git.DefaultContext == nil {
+ if err = git.InitSimple(context.Background()); err != nil {
+ return err
+ }
+ }
+
+ // Migrate
+ for i, m := range migrations[v:] {
+ log.Info("Migration[%d]: %s", v+int64(i), m.description)
+ // Reset the mapper between each migration - migrations are not supposed to depend on each other
+ x.SetMapper(names.GonicMapper{})
+ if err = m.migrate(x); err != nil {
+ return fmt.Errorf("migration[%d]: %s failed: %w", v+int64(i), m.description, err)
+ }
+ currentVersion.Version = v + int64(i) + 1
+ if _, err = x.ID(1).Update(currentVersion); err != nil {
+ return err
+ }
+ }
+
+ if err := x.Sync(new(semver.ForgejoSemVer)); err != nil {
+ return fmt.Errorf("sync: %w", err)
+ }
+
+ return semver.SetVersionStringWithEngine(x, setting.ForgejoVersion)
+}
diff --git a/models/forgejo_migrations/migrate_test.go b/models/forgejo_migrations/migrate_test.go
new file mode 100644
index 0000000..48ee4f7
--- /dev/null
+++ b/models/forgejo_migrations/migrate_test.go
@@ -0,0 +1,39 @@
+// Copyright 2023 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import (
+ "testing"
+
+ migration_tests "code.gitea.io/gitea/models/migrations/test"
+
+ "github.com/stretchr/testify/require"
+)
+
+// TestEnsureUpToDate tests the behavior of EnsureUpToDate.
+func TestEnsureUpToDate(t *testing.T) {
+ x, deferable := migration_tests.PrepareTestEnv(t, 0, new(ForgejoVersion))
+ defer deferable()
+ if x == nil || t.Failed() {
+ return
+ }
+
+ // Ensure error if there's no row in Forgejo Version.
+ err := EnsureUpToDate(x)
+ require.Error(t, err)
+
+ // Insert 'good' Forgejo Version row.
+ _, err = x.InsertOne(&ForgejoVersion{ID: 1, Version: ExpectedVersion()})
+ require.NoError(t, err)
+
+ err = EnsureUpToDate(x)
+ require.NoError(t, err)
+
+ // Modify forgejo version to have a lower version.
+ _, err = x.Exec("UPDATE `forgejo_version` SET version = ? WHERE id = 1", ExpectedVersion()-1)
+ require.NoError(t, err)
+
+ err = EnsureUpToDate(x)
+ require.Error(t, err)
+}
diff --git a/models/forgejo_migrations/v13.go b/models/forgejo_migrations/v13.go
new file mode 100644
index 0000000..614f682
--- /dev/null
+++ b/models/forgejo_migrations/v13.go
@@ -0,0 +1,15 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import "xorm.io/xorm"
+
+func AddHideArchiveLinksToRelease(x *xorm.Engine) error {
+ type Release struct {
+ ID int64 `xorm:"pk autoincr"`
+ HideArchiveLinks bool `xorm:"NOT NULL DEFAULT false"`
+ }
+
+ return x.Sync(&Release{})
+}
diff --git a/models/forgejo_migrations/v14.go b/models/forgejo_migrations/v14.go
new file mode 100644
index 0000000..f6dd35e
--- /dev/null
+++ b/models/forgejo_migrations/v14.go
@@ -0,0 +1,43 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import (
+ "code.gitea.io/gitea/models/migrations/base"
+
+ "xorm.io/xorm"
+)
+
+func RemoveGiteaSpecificColumnsFromRepositoryAndBadge(x *xorm.Engine) error {
+ // Make sure the columns exist before dropping them
+ type Repository struct {
+ ID int64
+ DefaultWikiBranch string
+ }
+ if err := x.Sync(&Repository{}); err != nil {
+ return err
+ }
+
+ type Badge struct {
+ ID int64 `xorm:"pk autoincr"`
+ Slug string
+ }
+ err := x.Sync(new(Badge))
+ if err != nil {
+ return err
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+ if err := base.DropTableColumns(sess, "repository", "default_wiki_branch"); err != nil {
+ return err
+ }
+ if err := base.DropTableColumns(sess, "badge", "slug"); err != nil {
+ return err
+ }
+ return sess.Commit()
+}
diff --git a/models/forgejo_migrations/v15.go b/models/forgejo_migrations/v15.go
new file mode 100644
index 0000000..d7ed19c
--- /dev/null
+++ b/models/forgejo_migrations/v15.go
@@ -0,0 +1,33 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import (
+ "time"
+
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+type (
+ SoftwareNameType string
+)
+
+type NodeInfo struct {
+ SoftwareName SoftwareNameType
+}
+
+type FederationHost struct {
+ ID int64 `xorm:"pk autoincr"`
+ HostFqdn string `xorm:"host_fqdn UNIQUE INDEX VARCHAR(255) NOT NULL"`
+ NodeInfo NodeInfo `xorm:"extends NOT NULL"`
+ LatestActivity time.Time `xorm:"NOT NULL"`
+ Created timeutil.TimeStamp `xorm:"created"`
+ Updated timeutil.TimeStamp `xorm:"updated"`
+}
+
+func CreateFederationHostTable(x *xorm.Engine) error {
+ return x.Sync(new(FederationHost))
+}
diff --git a/models/forgejo_migrations/v16.go b/models/forgejo_migrations/v16.go
new file mode 100644
index 0000000..f80bfc5
--- /dev/null
+++ b/models/forgejo_migrations/v16.go
@@ -0,0 +1,17 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import "xorm.io/xorm"
+
+type FederatedUser struct {
+ ID int64 `xorm:"pk autoincr"`
+ UserID int64 `xorm:"NOT NULL"`
+ ExternalID string `xorm:"UNIQUE(federation_user_mapping) NOT NULL"`
+ FederationHostID int64 `xorm:"UNIQUE(federation_user_mapping) NOT NULL"`
+}
+
+func CreateFederatedUserTable(x *xorm.Engine) error {
+ return x.Sync(new(FederatedUser))
+}
diff --git a/models/forgejo_migrations/v17.go b/models/forgejo_migrations/v17.go
new file mode 100644
index 0000000..d6e2983
--- /dev/null
+++ b/models/forgejo_migrations/v17.go
@@ -0,0 +1,14 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import "xorm.io/xorm"
+
+func AddNormalizedFederatedURIToUser(x *xorm.Engine) error {
+ type User struct {
+ ID int64 `xorm:"pk autoincr"`
+ NormalizedFederatedURI string
+ }
+ return x.Sync(&User{})
+}
diff --git a/models/forgejo_migrations/v18.go b/models/forgejo_migrations/v18.go
new file mode 100644
index 0000000..afccfbf
--- /dev/null
+++ b/models/forgejo_migrations/v18.go
@@ -0,0 +1,18 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import "xorm.io/xorm"
+
+type FollowingRepo struct {
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64 `xorm:"UNIQUE(federation_repo_mapping) NOT NULL"`
+ ExternalID string `xorm:"UNIQUE(federation_repo_mapping) NOT NULL"`
+ FederationHostID int64 `xorm:"UNIQUE(federation_repo_mapping) NOT NULL"`
+ URI string
+}
+
+func CreateFollowingRepoTable(x *xorm.Engine) error {
+ return x.Sync(new(FederatedUser))
+}
diff --git a/models/forgejo_migrations/v19.go b/models/forgejo_migrations/v19.go
new file mode 100644
index 0000000..69b7746
--- /dev/null
+++ b/models/forgejo_migrations/v19.go
@@ -0,0 +1,14 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import "xorm.io/xorm"
+
+func AddExternalURLColumnToAttachmentTable(x *xorm.Engine) error {
+ type Attachment struct {
+ ID int64 `xorm:"pk autoincr"`
+ ExternalURL string
+ }
+ return x.Sync(new(Attachment))
+}
diff --git a/models/forgejo_migrations/v1_20/v1.go b/models/forgejo_migrations/v1_20/v1.go
new file mode 100644
index 0000000..1097613
--- /dev/null
+++ b/models/forgejo_migrations/v1_20/v1.go
@@ -0,0 +1,21 @@
+// Copyright 2023 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_v1_20 //nolint:revive
+
+import (
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func AddForgejoBlockedUser(x *xorm.Engine) error {
+ type ForgejoBlockedUser struct {
+ ID int64 `xorm:"pk autoincr"`
+ BlockID int64 `xorm:"index"`
+ UserID int64 `xorm:"index"`
+ CreatedUnix timeutil.TimeStamp `xorm:"created"`
+ }
+
+ return x.Sync(new(ForgejoBlockedUser))
+}
diff --git a/models/forgejo_migrations/v1_20/v2.go b/models/forgejo_migrations/v1_20/v2.go
new file mode 100644
index 0000000..39f3b58
--- /dev/null
+++ b/models/forgejo_migrations/v1_20/v2.go
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: MIT
+
+package forgejo_v1_20 //nolint:revive
+
+import (
+ "xorm.io/xorm"
+)
+
+func CreateSemVerTable(x *xorm.Engine) error {
+ type ForgejoSemVer struct {
+ Version string
+ }
+
+ return x.Sync(new(ForgejoSemVer))
+}
diff --git a/models/forgejo_migrations/v1_20/v3.go b/models/forgejo_migrations/v1_20/v3.go
new file mode 100644
index 0000000..caa4f1a
--- /dev/null
+++ b/models/forgejo_migrations/v1_20/v3.go
@@ -0,0 +1,26 @@
+// Copyright 2023 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_v1_20 //nolint:revive
+
+import (
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+type AuthorizationToken struct {
+ ID int64 `xorm:"pk autoincr"`
+ UID int64 `xorm:"INDEX"`
+ LookupKey string `xorm:"INDEX UNIQUE"`
+ HashedValidator string
+ Expiry timeutil.TimeStamp
+}
+
+func (AuthorizationToken) TableName() string {
+ return "forgejo_auth_token"
+}
+
+func CreateAuthorizationTokenTable(x *xorm.Engine) error {
+ return x.Sync(new(AuthorizationToken))
+}
diff --git a/models/forgejo_migrations/v1_22/main_test.go b/models/forgejo_migrations/v1_22/main_test.go
new file mode 100644
index 0000000..0971108
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/main_test.go
@@ -0,0 +1,14 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import (
+ "testing"
+
+ migration_tests "code.gitea.io/gitea/models/migrations/test"
+)
+
+func TestMain(m *testing.M) {
+ migration_tests.MainTest(m)
+}
diff --git a/models/forgejo_migrations/v1_22/v10.go b/models/forgejo_migrations/v1_22/v10.go
new file mode 100644
index 0000000..819800a
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v10.go
@@ -0,0 +1,17 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddPronounsToUser(x *xorm.Engine) error {
+ type User struct {
+ ID int64 `xorm:"pk autoincr"`
+ Pronouns string
+ }
+
+ return x.Sync(&User{})
+}
diff --git a/models/forgejo_migrations/v1_22/v11.go b/models/forgejo_migrations/v1_22/v11.go
new file mode 100644
index 0000000..c693993
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v11.go
@@ -0,0 +1,19 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import (
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func AddCreatedToIssue(x *xorm.Engine) error {
+ type Issue struct {
+ ID int64 `xorm:"pk autoincr"`
+ Created timeutil.TimeStampNano
+ }
+
+ return x.Sync(&Issue{})
+}
diff --git a/models/forgejo_migrations/v1_22/v12.go b/models/forgejo_migrations/v1_22/v12.go
new file mode 100644
index 0000000..6822524
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v12.go
@@ -0,0 +1,18 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import "xorm.io/xorm"
+
+func AddRepoArchiveDownloadCount(x *xorm.Engine) error {
+ type RepoArchiveDownloadCount struct {
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64 `xorm:"index unique(s)"`
+ ReleaseID int64 `xorm:"index unique(s)"`
+ Type int `xorm:"unique(s)"`
+ Count int64
+ }
+
+ return x.Sync(&RepoArchiveDownloadCount{})
+}
diff --git a/models/forgejo_migrations/v1_22/v4.go b/models/forgejo_migrations/v1_22/v4.go
new file mode 100644
index 0000000..f1195f5
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v4.go
@@ -0,0 +1,17 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddDefaultPermissionsToRepoUnit(x *xorm.Engine) error {
+ type RepoUnit struct {
+ ID int64
+ DefaultPermissions int `xorm:"NOT NULL DEFAULT 0"`
+ }
+
+ return x.Sync(&RepoUnit{})
+}
diff --git a/models/forgejo_migrations/v1_22/v5.go b/models/forgejo_migrations/v1_22/v5.go
new file mode 100644
index 0000000..55f9fe1
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v5.go
@@ -0,0 +1,22 @@
+// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+type RepoFlag struct {
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64 `xorm:"UNIQUE(s) INDEX"`
+ Name string `xorm:"UNIQUE(s) INDEX"`
+}
+
+func (RepoFlag) TableName() string {
+ return "forgejo_repo_flag"
+}
+
+func CreateRepoFlagTable(x *xorm.Engine) error {
+ return x.Sync(new(RepoFlag))
+}
diff --git a/models/forgejo_migrations/v1_22/v6.go b/models/forgejo_migrations/v1_22/v6.go
new file mode 100644
index 0000000..1a48748
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v6.go
@@ -0,0 +1,24 @@
+// Copyright 2024 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddWikiBranchToRepository(x *xorm.Engine) error {
+ type Repository struct {
+ ID int64 `xorm:"pk autoincr"`
+ WikiBranch string
+ }
+
+ if err := x.Sync(&Repository{}); err != nil {
+ return err
+ }
+
+ // Update existing repositories to use `master` as the wiki branch, for
+ // compatilibty's sake.
+ _, err := x.Exec("UPDATE repository SET wiki_branch = 'master' WHERE wiki_branch = '' OR wiki_branch IS NULL")
+ return err
+}
diff --git a/models/forgejo_migrations/v1_22/v7.go b/models/forgejo_migrations/v1_22/v7.go
new file mode 100644
index 0000000..b42dd1a
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v7.go
@@ -0,0 +1,17 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddUserRepoUnitHintsSetting(x *xorm.Engine) error {
+ type User struct {
+ ID int64 `xorm:"pk autoincr"`
+ EnableRepoUnitHints bool `xorm:"NOT NULL DEFAULT true"`
+ }
+
+ return x.Sync(&User{})
+}
diff --git a/models/forgejo_migrations/v1_22/v8.go b/models/forgejo_migrations/v1_22/v8.go
new file mode 100644
index 0000000..2d3c0c5
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v8.go
@@ -0,0 +1,51 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import (
+ "strings"
+
+ "xorm.io/xorm"
+)
+
+func RemoveSSHSignaturesFromReleaseNotes(x *xorm.Engine) error {
+ type Release struct {
+ ID int64 `xorm:"pk autoincr"`
+ Note string `xorm:"TEXT"`
+ }
+
+ if err := x.Sync(&Release{}); err != nil {
+ return err
+ }
+
+ var releaseNotes []struct {
+ ID int64
+ Note string
+ }
+
+ if err := x.Table("release").Where("note LIKE '%-----BEGIN SSH SIGNATURE-----%'").Find(&releaseNotes); err != nil {
+ return err
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ for _, release := range releaseNotes {
+ idx := strings.LastIndex(release.Note, "-----BEGIN SSH SIGNATURE-----")
+ if idx == -1 {
+ continue
+ }
+ release.Note = release.Note[:idx]
+ _, err := sess.Exec("UPDATE `release` SET note = ? WHERE id = ?", release.Note, release.ID)
+ if err != nil {
+ return err
+ }
+ }
+
+ return sess.Commit()
+}
diff --git a/models/forgejo_migrations/v1_22/v8_test.go b/models/forgejo_migrations/v1_22/v8_test.go
new file mode 100644
index 0000000..128fd08
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v8_test.go
@@ -0,0 +1,35 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import (
+ "testing"
+
+ migration_tests "code.gitea.io/gitea/models/migrations/test"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func Test_RemoveSSHSignaturesFromReleaseNotes(t *testing.T) {
+ // A reduced mock of the `repo_model.Release` struct.
+ type Release struct {
+ ID int64 `xorm:"pk autoincr"`
+ Note string `xorm:"TEXT"`
+ }
+
+ x, deferable := migration_tests.PrepareTestEnv(t, 0, new(Release))
+ defer deferable()
+
+ require.NoError(t, RemoveSSHSignaturesFromReleaseNotes(x))
+
+ var releases []Release
+ err := x.Table("release").OrderBy("id ASC").Find(&releases)
+ require.NoError(t, err)
+ assert.Len(t, releases, 3)
+
+ assert.Equal(t, "", releases[0].Note)
+ assert.Equal(t, "A message.\n", releases[1].Note)
+ assert.Equal(t, "no signature present here", releases[2].Note)
+}
diff --git a/models/forgejo_migrations/v1_22/v9.go b/models/forgejo_migrations/v1_22/v9.go
new file mode 100644
index 0000000..34c2844
--- /dev/null
+++ b/models/forgejo_migrations/v1_22/v9.go
@@ -0,0 +1,15 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_22 //nolint
+
+import "xorm.io/xorm"
+
+func AddApplyToAdminsSetting(x *xorm.Engine) error {
+ type ProtectedBranch struct {
+ ID int64 `xorm:"pk autoincr"`
+ ApplyToAdmins bool `xorm:"NOT NULL DEFAULT false"`
+ }
+
+ return x.Sync(&ProtectedBranch{})
+}
diff --git a/models/forgejo_migrations/v20.go b/models/forgejo_migrations/v20.go
new file mode 100644
index 0000000..8ca9e91
--- /dev/null
+++ b/models/forgejo_migrations/v20.go
@@ -0,0 +1,52 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import "xorm.io/xorm"
+
+type (
+ QuotaLimitSubject int
+ QuotaLimitSubjects []QuotaLimitSubject
+
+ QuotaKind int
+)
+
+type QuotaRule struct {
+ Name string `xorm:"pk not null"`
+ Limit int64 `xorm:"NOT NULL"`
+ Subjects QuotaLimitSubjects
+}
+
+type QuotaGroup struct {
+ Name string `xorm:"pk NOT NULL"`
+}
+
+type QuotaGroupRuleMapping struct {
+ ID int64 `xorm:"pk autoincr"`
+ GroupName string `xorm:"index unique(qgrm_gr) not null"`
+ RuleName string `xorm:"unique(qgrm_gr) not null"`
+}
+
+type QuotaGroupMapping struct {
+ ID int64 `xorm:"pk autoincr"`
+ Kind QuotaKind `xorm:"unique(qgm_kmg) not null"`
+ MappedID int64 `xorm:"unique(qgm_kmg) not null"`
+ GroupName string `xorm:"index unique(qgm_kmg) not null"`
+}
+
+func CreateQuotaTables(x *xorm.Engine) error {
+ if err := x.Sync(new(QuotaRule)); err != nil {
+ return err
+ }
+
+ if err := x.Sync(new(QuotaGroup)); err != nil {
+ return err
+ }
+
+ if err := x.Sync(new(QuotaGroupRuleMapping)); err != nil {
+ return err
+ }
+
+ return x.Sync(new(QuotaGroupMapping))
+}
diff --git a/models/forgejo_migrations/v21.go b/models/forgejo_migrations/v21.go
new file mode 100644
index 0000000..53f141b
--- /dev/null
+++ b/models/forgejo_migrations/v21.go
@@ -0,0 +1,16 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import "xorm.io/xorm"
+
+func AddSSHKeypairToPushMirror(x *xorm.Engine) error {
+ type PushMirror struct {
+ ID int64 `xorm:"pk autoincr"`
+ PublicKey string `xorm:"VARCHAR(100)"`
+ PrivateKey []byte `xorm:"BLOB"`
+ }
+
+ return x.Sync(&PushMirror{})
+}
diff --git a/models/forgejo_migrations/v22.go b/models/forgejo_migrations/v22.go
new file mode 100644
index 0000000..eeb7387
--- /dev/null
+++ b/models/forgejo_migrations/v22.go
@@ -0,0 +1,17 @@
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package forgejo_migrations //nolint:revive
+
+import "xorm.io/xorm"
+
+func AddLegacyToWebAuthnCredential(x *xorm.Engine) error {
+ type WebauthnCredential struct {
+ ID int64 `xorm:"pk autoincr"`
+ BackupEligible bool `xorm:"NOT NULL DEFAULT false"`
+ BackupState bool `xorm:"NOT NULL DEFAULT false"`
+ Legacy bool `xorm:"NOT NULL DEFAULT true"`
+ }
+
+ return x.Sync(&WebauthnCredential{})
+}