mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in NOTICE, alongside LICENSE. The header lint accepts any copyright line above the SPDX line, so it no longer demands an upstream one. Co-authored-by: Hanzo Dev <[email protected]>
108 lines
2.6 KiB
Go
108 lines
2.6 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package v1_22
|
|
|
|
import (
|
|
"github.com/hanzoai/git/models/db"
|
|
"github.com/hanzoai/git/modules/setting"
|
|
"github.com/hanzoai/git/modules/timeutil"
|
|
)
|
|
|
|
// CheckProjectColumnsConsistency ensures there is exactly one default board per project present
|
|
func CheckProjectColumnsConsistency(x db.EngineMigration) error {
|
|
sess := x.NewSession()
|
|
defer sess.Close()
|
|
|
|
limit := setting.Database.IterateBufferSize
|
|
if limit <= 0 {
|
|
limit = 50
|
|
}
|
|
|
|
type Project struct {
|
|
ID int64
|
|
CreatorID int64
|
|
BoardID int64
|
|
}
|
|
|
|
type ProjectBoard struct {
|
|
ID int64 `xorm:"pk autoincr"`
|
|
Title string
|
|
Default bool `xorm:"NOT NULL DEFAULT false"` // issues not assigned to a specific board will be assigned to this board
|
|
Sorting int8 `xorm:"NOT NULL DEFAULT 0"`
|
|
Color string `xorm:"VARCHAR(7)"`
|
|
|
|
ProjectID int64 `xorm:"INDEX NOT NULL"`
|
|
CreatorID int64 `xorm:"NOT NULL"`
|
|
|
|
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
|
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
|
}
|
|
|
|
for {
|
|
if err := sess.Begin(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// all these projects without defaults will be fixed in the same loop, so
|
|
// we just need to always get projects without defaults until no such project
|
|
var projects []*Project
|
|
if err := sess.Select("project.id as id, project.creator_id, project_board.id as board_id").
|
|
Join("LEFT", "project_board", "project_board.project_id = project.id AND project_board.`default`=?", true).
|
|
Where("project_board.id is NULL OR project_board.id = 0").
|
|
Limit(limit).
|
|
Find(&projects); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, p := range projects {
|
|
if _, err := sess.Insert(ProjectBoard{
|
|
ProjectID: p.ID,
|
|
Default: true,
|
|
Title: "Uncategorized",
|
|
CreatorID: p.CreatorID,
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := sess.Commit(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(projects) == 0 {
|
|
break
|
|
}
|
|
}
|
|
sess.Close()
|
|
|
|
return removeDuplicatedBoardDefault(x)
|
|
}
|
|
|
|
func removeDuplicatedBoardDefault(x db.EngineMigration) error {
|
|
type ProjectInfo struct {
|
|
ProjectID int64
|
|
DefaultNum int
|
|
}
|
|
var projects []ProjectInfo
|
|
if err := x.Select("project_id, count(*) AS default_num").
|
|
Table("project_board").
|
|
Where("`default` = ?", true).
|
|
GroupBy("project_id").
|
|
Having("count(*) > 1").
|
|
Find(&projects); err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, project := range projects {
|
|
if _, err := x.Where("project_id=?", project.ProjectID).
|
|
Table("project_board").
|
|
Limit(project.DefaultNum - 1).
|
|
Update(map[string]bool{
|
|
"`default`": false,
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|