summaryrefslogtreecommitdiffstats
path: root/models/migrations/v1_15
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-10-18 20:33:49 +0200
committerDaniel Baumann <daniel@debian.org>2024-12-12 23:57:56 +0100
commite68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch)
tree97775d6c13b0f416af55314eb6a89ef792474615 /models/migrations/v1_15
parentInitial commit. (diff)
downloadforgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz
forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'models/migrations/v1_15')
-rw-r--r--models/migrations/v1_15/main_test.go14
-rw-r--r--models/migrations/v1_15/v178.go17
-rw-r--r--models/migrations/v1_15/v179.go28
-rw-r--r--models/migrations/v1_15/v180.go121
-rw-r--r--models/migrations/v1_15/v181.go91
-rw-r--r--models/migrations/v1_15/v181_test.go56
-rw-r--r--models/migrations/v1_15/v182.go41
-rw-r--r--models/migrations/v1_15/v182_test.go61
-rw-r--r--models/migrations/v1_15/v183.go38
-rw-r--r--models/migrations/v1_15/v184.go66
-rw-r--r--models/migrations/v1_15/v185.go21
-rw-r--r--models/migrations/v1_15/v186.go25
-rw-r--r--models/migrations/v1_15/v187.go47
-rw-r--r--models/migrations/v1_15/v188.go14
14 files changed, 640 insertions, 0 deletions
diff --git a/models/migrations/v1_15/main_test.go b/models/migrations/v1_15/main_test.go
new file mode 100644
index 0000000..e496065
--- /dev/null
+++ b/models/migrations/v1_15/main_test.go
@@ -0,0 +1,14 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //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/migrations/v1_15/v178.go b/models/migrations/v1_15/v178.go
new file mode 100644
index 0000000..6d236eb
--- /dev/null
+++ b/models/migrations/v1_15/v178.go
@@ -0,0 +1,17 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddLFSMirrorColumns(x *xorm.Engine) error {
+ type Mirror struct {
+ LFS bool `xorm:"lfs_enabled NOT NULL DEFAULT false"`
+ LFSEndpoint string `xorm:"lfs_endpoint TEXT"`
+ }
+
+ return x.Sync(new(Mirror))
+}
diff --git a/models/migrations/v1_15/v179.go b/models/migrations/v1_15/v179.go
new file mode 100644
index 0000000..f6b142e
--- /dev/null
+++ b/models/migrations/v1_15/v179.go
@@ -0,0 +1,28 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "code.gitea.io/gitea/models/migrations/base"
+
+ "xorm.io/xorm"
+ "xorm.io/xorm/schemas"
+)
+
+func ConvertAvatarURLToText(x *xorm.Engine) error {
+ dbType := x.Dialect().URI().DBType
+ if dbType == schemas.SQLITE { // For SQLITE, varchar or char will always be represented as TEXT
+ return nil
+ }
+
+ // Some oauth2 providers may give very long avatar urls (i.e. Google)
+ return base.ModifyColumn(x, "external_login_user", &schemas.Column{
+ Name: "avatar_url",
+ SQLType: schemas.SQLType{
+ Name: schemas.Text,
+ },
+ Nullable: true,
+ DefaultIsEmpty: true,
+ })
+}
diff --git a/models/migrations/v1_15/v180.go b/models/migrations/v1_15/v180.go
new file mode 100644
index 0000000..c71e771
--- /dev/null
+++ b/models/migrations/v1_15/v180.go
@@ -0,0 +1,121 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "code.gitea.io/gitea/modules/json"
+ "code.gitea.io/gitea/modules/util"
+
+ "xorm.io/builder"
+ "xorm.io/xorm"
+)
+
+func DeleteMigrationCredentials(x *xorm.Engine) (err error) {
+ // Task represents a task
+ type Task struct {
+ ID int64
+ DoerID int64 `xorm:"index"` // operator
+ OwnerID int64 `xorm:"index"` // repo owner id, when creating, the repoID maybe zero
+ RepoID int64 `xorm:"index"`
+ Type int
+ Status int `xorm:"index"`
+ StartTime int64
+ EndTime int64
+ PayloadContent string `xorm:"TEXT"`
+ Errors string `xorm:"TEXT"` // if task failed, saved the error reason
+ Created int64 `xorm:"created"`
+ }
+
+ const TaskTypeMigrateRepo = 0
+ const TaskStatusStopped = 2
+
+ const batchSize = 100
+
+ // only match migration tasks, that are not pending or running
+ cond := builder.Eq{
+ "type": TaskTypeMigrateRepo,
+ }.And(builder.Gte{
+ "status": TaskStatusStopped,
+ })
+
+ sess := x.NewSession()
+ defer sess.Close()
+
+ for start := 0; ; start += batchSize {
+ tasks := make([]*Task, 0, batchSize)
+ if err := sess.Limit(batchSize, start).Where(cond, 0).Find(&tasks); err != nil {
+ return err
+ }
+ if len(tasks) == 0 {
+ break
+ }
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+ for _, t := range tasks {
+ if t.PayloadContent, err = removeCredentials(t.PayloadContent); err != nil {
+ return err
+ }
+ if _, err := sess.ID(t.ID).Cols("payload_content").Update(t); err != nil {
+ return err
+ }
+ }
+ if err := sess.Commit(); err != nil {
+ return err
+ }
+ }
+ return err
+}
+
+func removeCredentials(payload string) (string, error) {
+ // MigrateOptions defines the way a repository gets migrated
+ // this is for internal usage by migrations module and func who interact with it
+ type MigrateOptions struct {
+ // required: true
+ CloneAddr string `json:"clone_addr" binding:"Required"`
+ CloneAddrEncrypted string `json:"clone_addr_encrypted,omitempty"`
+ AuthUsername string `json:"auth_username"`
+ AuthPassword string `json:"-"`
+ AuthPasswordEncrypted string `json:"auth_password_encrypted,omitempty"`
+ AuthToken string `json:"-"`
+ AuthTokenEncrypted string `json:"auth_token_encrypted,omitempty"`
+ // required: true
+ UID int `json:"uid" binding:"Required"`
+ // required: true
+ RepoName string `json:"repo_name" binding:"Required"`
+ Mirror bool `json:"mirror"`
+ LFS bool `json:"lfs"`
+ LFSEndpoint string `json:"lfs_endpoint"`
+ Private bool `json:"private"`
+ Description string `json:"description"`
+ OriginalURL string
+ GitServiceType int
+ Wiki bool
+ Issues bool
+ Milestones bool
+ Labels bool
+ Releases bool
+ Comments bool
+ PullRequests bool
+ ReleaseAssets bool
+ MigrateToRepoID int64
+ MirrorInterval string `json:"mirror_interval"`
+ }
+
+ var opts MigrateOptions
+ err := json.Unmarshal([]byte(payload), &opts)
+ if err != nil {
+ return "", err
+ }
+
+ opts.AuthPassword = ""
+ opts.AuthToken = ""
+ opts.CloneAddr = util.SanitizeCredentialURLs(opts.CloneAddr)
+
+ confBytes, err := json.Marshal(opts)
+ if err != nil {
+ return "", err
+ }
+ return string(confBytes), nil
+}
diff --git a/models/migrations/v1_15/v181.go b/models/migrations/v1_15/v181.go
new file mode 100644
index 0000000..2185ed0
--- /dev/null
+++ b/models/migrations/v1_15/v181.go
@@ -0,0 +1,91 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "strings"
+
+ "xorm.io/xorm"
+)
+
+func AddPrimaryEmail2EmailAddress(x *xorm.Engine) error {
+ type User struct {
+ ID int64 `xorm:"pk autoincr"`
+ Email string `xorm:"NOT NULL"`
+ IsActive bool `xorm:"INDEX"` // Activate primary email
+ }
+
+ type EmailAddress1 struct {
+ ID int64 `xorm:"pk autoincr"`
+ UID int64 `xorm:"INDEX NOT NULL"`
+ Email string `xorm:"UNIQUE NOT NULL"`
+ LowerEmail string
+ IsActivated bool
+ IsPrimary bool `xorm:"DEFAULT(false) NOT NULL"`
+ }
+
+ // Add lower_email and is_primary columns
+ if err := x.Table("email_address").Sync(new(EmailAddress1)); err != nil {
+ return err
+ }
+
+ if _, err := x.Exec("UPDATE email_address SET lower_email=LOWER(email), is_primary=?", false); err != nil {
+ return err
+ }
+
+ type EmailAddress struct {
+ ID int64 `xorm:"pk autoincr"`
+ UID int64 `xorm:"INDEX NOT NULL"`
+ Email string `xorm:"UNIQUE NOT NULL"`
+ LowerEmail string `xorm:"UNIQUE NOT NULL"`
+ IsActivated bool
+ IsPrimary bool `xorm:"DEFAULT(false) NOT NULL"`
+ }
+
+ // change lower_email as unique
+ if err := x.Sync(new(EmailAddress)); err != nil {
+ return err
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+
+ const batchSize = 100
+
+ for start := 0; ; start += batchSize {
+ users := make([]*User, 0, batchSize)
+ if err := sess.Limit(batchSize, start).Find(&users); err != nil {
+ return err
+ }
+ if len(users) == 0 {
+ break
+ }
+
+ for _, user := range users {
+ exist, err := sess.Where("email=?", user.Email).Table("email_address").Exist()
+ if err != nil {
+ return err
+ }
+ if !exist {
+ if _, err := sess.Insert(&EmailAddress{
+ UID: user.ID,
+ Email: user.Email,
+ LowerEmail: strings.ToLower(user.Email),
+ IsActivated: user.IsActive,
+ IsPrimary: true,
+ }); err != nil {
+ return err
+ }
+ } else {
+ if _, err := sess.Where("email=?", user.Email).Cols("is_primary").Update(&EmailAddress{
+ IsPrimary: true,
+ }); err != nil {
+ return err
+ }
+ }
+ }
+ }
+
+ return nil
+}
diff --git a/models/migrations/v1_15/v181_test.go b/models/migrations/v1_15/v181_test.go
new file mode 100644
index 0000000..ead26f5
--- /dev/null
+++ b/models/migrations/v1_15/v181_test.go
@@ -0,0 +1,56 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "strings"
+ "testing"
+
+ migration_tests "code.gitea.io/gitea/models/migrations/test"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func Test_AddPrimaryEmail2EmailAddress(t *testing.T) {
+ type User struct {
+ ID int64
+ Email string
+ IsActive bool
+ }
+
+ // Prepare and load the testing database
+ x, deferable := migration_tests.PrepareTestEnv(t, 0, new(User))
+ if x == nil || t.Failed() {
+ defer deferable()
+ return
+ }
+ defer deferable()
+
+ err := AddPrimaryEmail2EmailAddress(x)
+ require.NoError(t, err)
+
+ type EmailAddress struct {
+ ID int64 `xorm:"pk autoincr"`
+ UID int64 `xorm:"INDEX NOT NULL"`
+ Email string `xorm:"UNIQUE NOT NULL"`
+ LowerEmail string `xorm:"UNIQUE NOT NULL"`
+ IsActivated bool
+ IsPrimary bool `xorm:"DEFAULT(false) NOT NULL"`
+ }
+
+ users := make([]User, 0, 20)
+ err = x.Find(&users)
+ require.NoError(t, err)
+
+ for _, user := range users {
+ var emailAddress EmailAddress
+ has, err := x.Where("lower_email=?", strings.ToLower(user.Email)).Get(&emailAddress)
+ require.NoError(t, err)
+ assert.True(t, has)
+ assert.True(t, emailAddress.IsPrimary)
+ assert.EqualValues(t, user.IsActive, emailAddress.IsActivated)
+ assert.EqualValues(t, user.ID, emailAddress.UID)
+ }
+}
diff --git a/models/migrations/v1_15/v182.go b/models/migrations/v1_15/v182.go
new file mode 100644
index 0000000..9ca500c
--- /dev/null
+++ b/models/migrations/v1_15/v182.go
@@ -0,0 +1,41 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddIssueResourceIndexTable(x *xorm.Engine) error {
+ type ResourceIndex struct {
+ GroupID int64 `xorm:"pk"`
+ MaxIndex int64 `xorm:"index"`
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ if err := sess.Table("issue_index").Sync(new(ResourceIndex)); err != nil {
+ return err
+ }
+
+ // Remove data we're goint to rebuild
+ if _, err := sess.Table("issue_index").Where("1=1").Delete(&ResourceIndex{}); err != nil {
+ return err
+ }
+
+ // Create current data for all repositories with issues and PRs
+ if _, err := sess.Exec("INSERT INTO issue_index (group_id, max_index) " +
+ "SELECT max_data.repo_id, max_data.max_index " +
+ "FROM ( SELECT issue.repo_id AS repo_id, max(issue.`index`) AS max_index " +
+ "FROM issue GROUP BY issue.repo_id) AS max_data"); err != nil {
+ return err
+ }
+
+ return sess.Commit()
+}
diff --git a/models/migrations/v1_15/v182_test.go b/models/migrations/v1_15/v182_test.go
new file mode 100644
index 0000000..eb21311
--- /dev/null
+++ b/models/migrations/v1_15/v182_test.go
@@ -0,0 +1,61 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "testing"
+
+ migration_tests "code.gitea.io/gitea/models/migrations/test"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func Test_AddIssueResourceIndexTable(t *testing.T) {
+ // Create the models used in the migration
+ type Issue struct {
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64 `xorm:"UNIQUE(s)"`
+ Index int64 `xorm:"UNIQUE(s)"`
+ }
+
+ // Prepare and load the testing database
+ x, deferable := migration_tests.PrepareTestEnv(t, 0, new(Issue))
+ if x == nil || t.Failed() {
+ defer deferable()
+ return
+ }
+ defer deferable()
+
+ // Run the migration
+ if err := AddIssueResourceIndexTable(x); err != nil {
+ require.NoError(t, err)
+ return
+ }
+
+ type ResourceIndex struct {
+ GroupID int64 `xorm:"pk"`
+ MaxIndex int64 `xorm:"index"`
+ }
+
+ start := 0
+ const batchSize = 1000
+ for {
+ indexes := make([]ResourceIndex, 0, batchSize)
+ err := x.Table("issue_index").Limit(batchSize, start).Find(&indexes)
+ require.NoError(t, err)
+
+ for _, idx := range indexes {
+ var maxIndex int
+ has, err := x.SQL("SELECT max(`index`) FROM issue WHERE repo_id = ?", idx.GroupID).Get(&maxIndex)
+ require.NoError(t, err)
+ assert.True(t, has)
+ assert.EqualValues(t, maxIndex, idx.MaxIndex)
+ }
+ if len(indexes) < batchSize {
+ break
+ }
+ start += len(indexes)
+ }
+}
diff --git a/models/migrations/v1_15/v183.go b/models/migrations/v1_15/v183.go
new file mode 100644
index 0000000..effad1b
--- /dev/null
+++ b/models/migrations/v1_15/v183.go
@@ -0,0 +1,38 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "fmt"
+ "time"
+
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func CreatePushMirrorTable(x *xorm.Engine) error {
+ type PushMirror struct {
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64 `xorm:"INDEX"`
+ RemoteName string
+
+ Interval time.Duration
+ CreatedUnix timeutil.TimeStamp `xorm:"created"`
+ LastUpdateUnix timeutil.TimeStamp `xorm:"INDEX last_update"`
+ LastError string `xorm:"text"`
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ if err := sess.Sync(new(PushMirror)); err != nil {
+ return fmt.Errorf("Sync: %w", err)
+ }
+
+ return sess.Commit()
+}
diff --git a/models/migrations/v1_15/v184.go b/models/migrations/v1_15/v184.go
new file mode 100644
index 0000000..871c9db
--- /dev/null
+++ b/models/migrations/v1_15/v184.go
@@ -0,0 +1,66 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "context"
+ "fmt"
+
+ "code.gitea.io/gitea/models/migrations/base"
+ "code.gitea.io/gitea/modules/setting"
+
+ "xorm.io/xorm"
+)
+
+func RenameTaskErrorsToMessage(x *xorm.Engine) error {
+ type Task struct {
+ Errors string `xorm:"TEXT"` // if task failed, saved the error reason
+ Type int
+ Status int `xorm:"index"`
+ }
+
+ // This migration maybe rerun so that we should check if it has been run
+ messageExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "task", "message")
+ if err != nil {
+ return err
+ }
+
+ if messageExist {
+ errorsExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "task", "errors")
+ if err != nil {
+ return err
+ }
+ if !errorsExist {
+ return nil
+ }
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ if err := sess.Sync(new(Task)); err != nil {
+ return fmt.Errorf("error on Sync: %w", err)
+ }
+
+ if messageExist {
+ // if both errors and message exist, drop message at first
+ if err := base.DropTableColumns(sess, "task", "message"); err != nil {
+ return err
+ }
+ }
+
+ if setting.Database.Type.IsMySQL() {
+ if _, err := sess.Exec("ALTER TABLE `task` CHANGE errors message text"); err != nil {
+ return err
+ }
+ } else {
+ if _, err := sess.Exec("ALTER TABLE `task` RENAME COLUMN errors TO message"); err != nil {
+ return err
+ }
+ }
+ return sess.Commit()
+}
diff --git a/models/migrations/v1_15/v185.go b/models/migrations/v1_15/v185.go
new file mode 100644
index 0000000..e5878ec
--- /dev/null
+++ b/models/migrations/v1_15/v185.go
@@ -0,0 +1,21 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "xorm.io/xorm"
+)
+
+func AddRepoArchiver(x *xorm.Engine) error {
+ // RepoArchiver represents all archivers
+ type RepoArchiver struct {
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64 `xorm:"index unique(s)"`
+ Type int `xorm:"unique(s)"`
+ Status int
+ CommitID string `xorm:"VARCHAR(40) unique(s)"`
+ CreatedUnix int64 `xorm:"INDEX NOT NULL created"`
+ }
+ return x.Sync(new(RepoArchiver))
+}
diff --git a/models/migrations/v1_15/v186.go b/models/migrations/v1_15/v186.go
new file mode 100644
index 0000000..01aab3a
--- /dev/null
+++ b/models/migrations/v1_15/v186.go
@@ -0,0 +1,25 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "code.gitea.io/gitea/modules/timeutil"
+
+ "xorm.io/xorm"
+)
+
+func CreateProtectedTagTable(x *xorm.Engine) error {
+ type ProtectedTag struct {
+ ID int64 `xorm:"pk autoincr"`
+ RepoID int64
+ NamePattern string
+ AllowlistUserIDs []int64 `xorm:"JSON TEXT"`
+ AllowlistTeamIDs []int64 `xorm:"JSON TEXT"`
+
+ CreatedUnix timeutil.TimeStamp `xorm:"created"`
+ UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
+ }
+
+ return x.Sync(new(ProtectedTag))
+}
diff --git a/models/migrations/v1_15/v187.go b/models/migrations/v1_15/v187.go
new file mode 100644
index 0000000..21cd677
--- /dev/null
+++ b/models/migrations/v1_15/v187.go
@@ -0,0 +1,47 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import (
+ "code.gitea.io/gitea/models/migrations/base"
+
+ "xorm.io/xorm"
+)
+
+func DropWebhookColumns(x *xorm.Engine) error {
+ // Make sure the columns exist before dropping them
+ type Webhook struct {
+ Signature string `xorm:"TEXT"`
+ IsSSL bool `xorm:"is_ssl"`
+ }
+ if err := x.Sync(new(Webhook)); err != nil {
+ return err
+ }
+
+ type HookTask struct {
+ Typ string `xorm:"VARCHAR(16) index"`
+ URL string `xorm:"TEXT"`
+ Signature string `xorm:"TEXT"`
+ HTTPMethod string `xorm:"http_method"`
+ ContentType int
+ IsSSL bool
+ }
+ if err := x.Sync(new(HookTask)); err != nil {
+ return err
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+ if err := base.DropTableColumns(sess, "webhook", "signature", "is_ssl"); err != nil {
+ return err
+ }
+ if err := base.DropTableColumns(sess, "hook_task", "typ", "url", "signature", "http_method", "content_type", "is_ssl"); err != nil {
+ return err
+ }
+
+ return sess.Commit()
+}
diff --git a/models/migrations/v1_15/v188.go b/models/migrations/v1_15/v188.go
new file mode 100644
index 0000000..71e45ca
--- /dev/null
+++ b/models/migrations/v1_15/v188.go
@@ -0,0 +1,14 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_15 //nolint
+
+import "xorm.io/xorm"
+
+func AddKeyIsVerified(x *xorm.Engine) error {
+ type GPGKey struct {
+ Verified bool `xorm:"NOT NULL DEFAULT false"`
+ }
+
+ return x.Sync(new(GPGKey))
+}