Merge remote-tracking branch 'upstream/main' into limit-repo-size

This commit is contained in:
DmitryFrolovTri
2023-05-23 06:04:57 +00:00
228 changed files with 6149 additions and 5925 deletions
+23 -29
View File
@@ -14,67 +14,62 @@ import (
// XORMLogBridge a logger bridge from Logger to xorm
type XORMLogBridge struct {
showSQLint *int32
logger log.Logger
showSQL atomic.Bool
logger log.Logger
}
// NewXORMLogger inits a log bridge for xorm
func NewXORMLogger(showSQL bool) xormlog.Logger {
showSQLint := int32(0)
if showSQL {
showSQLint = 1
}
return &XORMLogBridge{
showSQLint: &showSQLint,
logger: log.GetLogger("xorm"),
}
l := &XORMLogBridge{logger: log.GetLogger("xorm")}
l.showSQL.Store(showSQL)
return l
}
const stackLevel = 8
// Log a message with defined skip and at logging level
func (l *XORMLogBridge) Log(skip int, level log.Level, format string, v ...interface{}) error {
return l.logger.Log(skip+1, level, format, v...)
func (l *XORMLogBridge) Log(skip int, level log.Level, format string, v ...interface{}) {
l.logger.Log(skip+1, level, format, v...)
}
// Debug show debug log
func (l *XORMLogBridge) Debug(v ...interface{}) {
_ = l.Log(stackLevel, log.DEBUG, fmt.Sprint(v...))
l.Log(stackLevel, log.DEBUG, "%s", fmt.Sprint(v...))
}
// Debugf show debug log
func (l *XORMLogBridge) Debugf(format string, v ...interface{}) {
_ = l.Log(stackLevel, log.DEBUG, format, v...)
l.Log(stackLevel, log.DEBUG, format, v...)
}
// Error show error log
func (l *XORMLogBridge) Error(v ...interface{}) {
_ = l.Log(stackLevel, log.ERROR, fmt.Sprint(v...))
l.Log(stackLevel, log.ERROR, "%s", fmt.Sprint(v...))
}
// Errorf show error log
func (l *XORMLogBridge) Errorf(format string, v ...interface{}) {
_ = l.Log(stackLevel, log.ERROR, format, v...)
l.Log(stackLevel, log.ERROR, format, v...)
}
// Info show information level log
func (l *XORMLogBridge) Info(v ...interface{}) {
_ = l.Log(stackLevel, log.INFO, fmt.Sprint(v...))
l.Log(stackLevel, log.INFO, "%s", fmt.Sprint(v...))
}
// Infof show information level log
func (l *XORMLogBridge) Infof(format string, v ...interface{}) {
_ = l.Log(stackLevel, log.INFO, format, v...)
l.Log(stackLevel, log.INFO, format, v...)
}
// Warn show warning log
func (l *XORMLogBridge) Warn(v ...interface{}) {
_ = l.Log(stackLevel, log.WARN, fmt.Sprint(v...))
l.Log(stackLevel, log.WARN, "%s", fmt.Sprint(v...))
}
// Warnf show warnning log
func (l *XORMLogBridge) Warnf(format string, v ...interface{}) {
_ = l.Log(stackLevel, log.WARN, format, v...)
l.Log(stackLevel, log.WARN, format, v...)
}
// Level get logger level
@@ -86,10 +81,12 @@ func (l *XORMLogBridge) Level() xormlog.LogLevel {
return xormlog.LOG_INFO
case log.WARN:
return xormlog.LOG_WARNING
case log.ERROR, log.CRITICAL:
case log.ERROR:
return xormlog.LOG_ERR
case log.NONE:
return xormlog.LOG_OFF
}
return xormlog.LOG_OFF
return xormlog.LOG_UNKNOWN
}
// SetLevel set the logger level
@@ -98,16 +95,13 @@ func (l *XORMLogBridge) SetLevel(lvl xormlog.LogLevel) {
// ShowSQL set if record SQL
func (l *XORMLogBridge) ShowSQL(show ...bool) {
showSQL := int32(1)
if len(show) > 0 && !show[0] {
showSQL = 0
if len(show) == 0 {
show = []bool{true}
}
atomic.StoreInt32(l.showSQLint, showSQL)
l.showSQL.Store(show[0])
}
// IsShowSQL if record SQL
func (l *XORMLogBridge) IsShowSQL() bool {
showSQL := atomic.LoadInt32(l.showSQLint)
return showSQL == 1
return l.showSQL.Load()
}
+1 -1
View File
@@ -1048,7 +1048,7 @@ func (opts *FindCommentsOptions) ToConds() builder.Cond {
}
// FindComments returns all comments according options
func FindComments(ctx context.Context, opts *FindCommentsOptions) ([]*Comment, error) {
func FindComments(ctx context.Context, opts *FindCommentsOptions) (CommentList, error) {
comments := make([]*Comment, 0, 10)
sess := db.GetEngine(ctx).Where(opts.ToConds())
if opts.RepoID > 0 {
+2 -2
View File
@@ -48,7 +48,7 @@ func fetchCodeCommentsByReview(ctx context.Context, issue *Issue, currentUser *u
}
func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issue, currentUser *user_model.User, review *Review) ([]*Comment, error) {
var comments []*Comment
var comments CommentList
if review == nil {
review = &Review{ID: 0}
}
@@ -68,7 +68,7 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu
return nil, err
}
if err := CommentList(comments).LoadPosters(ctx); err != nil {
if err := comments.LoadPosters(ctx); err != nil {
return nil, err
}
+2 -2
View File
@@ -124,7 +124,7 @@ type Issue struct {
ClosedUnix timeutil.TimeStamp `xorm:"INDEX"`
Attachments []*repo_model.Attachment `xorm:"-"`
Comments []*Comment `xorm:"-"`
Comments CommentList `xorm:"-"`
Reactions ReactionList `xorm:"-"`
TotalTrackedTime int64 `xorm:"-"`
Assignees []*user_model.User `xorm:"-"`
@@ -353,7 +353,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
return err
}
if err = CommentList(issue.Comments).loadAttributes(ctx); err != nil {
if err = issue.Comments.loadAttributes(ctx); err != nil {
return err
}
if issue.IsTimetrackerEnabled(ctx) {
+1 -1
View File
@@ -141,7 +141,7 @@ func getIssueStatsChunk(opts *IssuesOptions, issueIDs []int64) (*IssueStats, err
if opts.AssigneeID > 0 {
applyAssigneeCondition(sess, opts.AssigneeID)
} else if opts.AssigneeID == db.NoConditionID {
sess.Where("id NOT IN (SELECT issue_id FROM issue_assignees)")
sess.Where("issue.id NOT IN (SELECT issue_id FROM issue_assignees)")
}
if opts.PosterID > 0 {
+11 -24
View File
@@ -224,40 +224,27 @@ func DeletePullsByBaseRepoID(ctx context.Context, repoID int64) error {
return err
}
// ColorFormat writes a colored string to identify this struct
func (pr *PullRequest) ColorFormat(s fmt.State) {
func (pr *PullRequest) String() string {
if pr == nil {
log.ColorFprintf(s, "PR[%d]%s#%d[%s...%s:%s]",
log.NewColoredIDValue(0),
log.NewColoredValue("<nil>/<nil>"),
log.NewColoredIDValue(0),
log.NewColoredValue("<nil>"),
log.NewColoredValue("<nil>/<nil>"),
log.NewColoredValue("<nil>"),
)
return
return "<PullRequest nil>"
}
log.ColorFprintf(s, "PR[%d]", log.NewColoredIDValue(pr.ID))
s := new(strings.Builder)
fmt.Fprintf(s, "<PullRequest [%d]", pr.ID)
if pr.BaseRepo != nil {
log.ColorFprintf(s, "%s#%d[%s...", log.NewColoredValue(pr.BaseRepo.FullName()),
log.NewColoredIDValue(pr.Index), log.NewColoredValue(pr.BaseBranch))
fmt.Fprintf(s, "%s#%d[%s...", pr.BaseRepo.FullName(), pr.Index, pr.BaseBranch)
} else {
log.ColorFprintf(s, "Repo[%d]#%d[%s...", log.NewColoredIDValue(pr.BaseRepoID),
log.NewColoredIDValue(pr.Index), log.NewColoredValue(pr.BaseBranch))
fmt.Fprintf(s, "Repo[%d]#%d[%s...", pr.BaseRepoID, pr.Index, pr.BaseBranch)
}
if pr.HeadRepoID == pr.BaseRepoID {
log.ColorFprintf(s, "%s]", log.NewColoredValue(pr.HeadBranch))
fmt.Fprintf(s, "%s]", pr.HeadBranch)
} else if pr.HeadRepo != nil {
log.ColorFprintf(s, "%s:%s]", log.NewColoredValue(pr.HeadRepo.FullName()), log.NewColoredValue(pr.HeadBranch))
fmt.Fprintf(s, "%s:%s]", pr.HeadRepo.FullName(), pr.HeadBranch)
} else {
log.ColorFprintf(s, "Repo[%d]:%s]", log.NewColoredIDValue(pr.HeadRepoID), log.NewColoredValue(pr.HeadBranch))
fmt.Fprintf(s, "Repo[%d]:%s]", pr.HeadRepoID, pr.HeadBranch)
}
}
// String represents the pr as a simple string
func (pr *PullRequest) String() string {
return log.ColorFormatAsString(pr)
s.WriteByte('>')
return s.String()
}
// MustHeadUserName returns the HeadRepo's username if failed return blank
+4 -2
View File
@@ -24,6 +24,8 @@ import (
"xorm.io/xorm"
)
// FIXME: this file shouldn't be in a normal package, it should only be compiled for tests
// PrepareTestEnv prepares the test environment and reset the database. The skip parameter should usually be 0.
// Provide models to be sync'd with the database - in particular any models you expect fixtures to be loaded from.
//
@@ -110,7 +112,7 @@ func PrepareTestEnv(t *testing.T, skip int, syncModels ...interface{}) (*xorm.En
}
func MainTest(m *testing.M) {
log.Register("test", testlogger.NewTestLogger)
log.RegisterEventWriter("test", testlogger.NewTestLoggerWriter)
giteaRoot := base.SetupGiteaRoot()
if giteaRoot == "" {
@@ -154,7 +156,7 @@ func MainTest(m *testing.M) {
os.Exit(1)
}
setting.LoadDBSetting()
setting.InitLogs(true)
setting.InitLoggersForTest()
exitStatus := m.Run()
+3 -13
View File
@@ -94,21 +94,11 @@ func init() {
db.RegisterModel(new(TeamInvite))
}
// ColorFormat provides a basic color format for a Team
func (t *Team) ColorFormat(s fmt.State) {
func (t *Team) LogString() string {
if t == nil {
log.ColorFprintf(s, "%d:%s (OrgID: %d) %-v",
log.NewColoredIDValue(0),
"<nil>",
log.NewColoredIDValue(0),
0)
return
return "<Team nil>"
}
log.ColorFprintf(s, "%d:%s (OrgID: %d) %-v",
log.NewColoredIDValue(t.ID),
t.Name,
log.NewColoredIDValue(t.OrgID),
t.AccessMode)
return fmt.Sprintf("<Team %d:%s OrgID=%d AccessMode=%s>", t.ID, t.Name, t.OrgID, t.AccessMode.LogString())
}
// LoadUnits load a list of available units for a team
+90
View File
@@ -0,0 +1,90 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package cran
import (
"context"
"strconv"
"strings"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/packages"
cran_module "code.gitea.io/gitea/modules/packages/cran"
"xorm.io/builder"
)
type SearchOptions struct {
OwnerID int64
FileType string
Platform string
RVersion string
Filename string
}
func (opts *SearchOptions) toConds() builder.Cond {
var cond builder.Cond = builder.Eq{
"package.type": packages.TypeCran,
"package.owner_id": opts.OwnerID,
"package_version.is_internal": false,
}
if opts.Filename != "" {
cond = cond.And(builder.Eq{"package_file.lower_name": strings.ToLower(opts.Filename)})
}
var propsCond builder.Cond = builder.Eq{
"package_property.ref_type": packages.PropertyTypeFile,
}
propsCond = propsCond.And(builder.Expr("package_property.ref_id = package_file.id"))
count := 1
propsCondBlock := builder.Eq{"package_property.name": cran_module.PropertyType}.And(builder.Eq{"package_property.value": opts.FileType})
if opts.Platform != "" {
count += 2
propsCondBlock = propsCondBlock.
Or(builder.Eq{"package_property.name": cran_module.PropertyPlatform}.And(builder.Eq{"package_property.value": opts.Platform})).
Or(builder.Eq{"package_property.name": cran_module.PropertyRVersion}.And(builder.Eq{"package_property.value": opts.RVersion}))
}
propsCond = propsCond.And(propsCondBlock)
cond = cond.And(builder.Eq{
strconv.Itoa(count): builder.Select("COUNT(*)").Where(propsCond).From("package_property"),
})
return cond
}
func SearchLatestVersions(ctx context.Context, opts *SearchOptions) ([]*packages.PackageVersion, error) {
sess := db.GetEngine(ctx).
Table("package_version").
Select("package_version.*").
Join("LEFT", "package_version pv2", builder.Expr("package_version.package_id = pv2.package_id AND pv2.is_internal = ? AND (package_version.created_unix < pv2.created_unix OR (package_version.created_unix = pv2.created_unix AND package_version.id < pv2.id))", false)).
Join("INNER", "package", "package.id = package_version.package_id").
Join("INNER", "package_file", "package_file.version_id = package_version.id").
Where(opts.toConds().And(builder.Expr("pv2.id IS NULL"))).
Asc("package.name")
pvs := make([]*packages.PackageVersion, 0, 10)
return pvs, sess.Find(&pvs)
}
func SearchFile(ctx context.Context, opts *SearchOptions) (*packages.PackageFile, error) {
sess := db.GetEngine(ctx).
Table("package_version").
Select("package_file.*").
Join("INNER", "package", "package.id = package_version.package_id").
Join("INNER", "package_file", "package_file.version_id = package_version.id").
Where(opts.toConds())
pf := &packages.PackageFile{}
if has, err := sess.Get(pf); err != nil {
return nil, err
} else if !has {
return nil, packages.ErrPackageFileNotExist
}
return pf, nil
}
+3
View File
@@ -19,6 +19,7 @@ import (
"code.gitea.io/gitea/modules/packages/conan"
"code.gitea.io/gitea/modules/packages/conda"
"code.gitea.io/gitea/modules/packages/container"
"code.gitea.io/gitea/modules/packages/cran"
"code.gitea.io/gitea/modules/packages/debian"
"code.gitea.io/gitea/modules/packages/helm"
"code.gitea.io/gitea/modules/packages/maven"
@@ -151,6 +152,8 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc
metadata = &conda.VersionMetadata{}
case TypeContainer:
metadata = &container.Metadata{}
case TypeCran:
metadata = &cran.Metadata{}
case TypeDebian:
metadata = &debian.Metadata{}
case TypeGeneric:
+6
View File
@@ -37,6 +37,7 @@ const (
TypeConan Type = "conan"
TypeConda Type = "conda"
TypeContainer Type = "container"
TypeCran Type = "cran"
TypeDebian Type = "debian"
TypeGeneric Type = "generic"
TypeGo Type = "go"
@@ -60,6 +61,7 @@ var TypeList = []Type{
TypeConan,
TypeConda,
TypeContainer,
TypeCran,
TypeDebian,
TypeGeneric,
TypeGo,
@@ -92,6 +94,8 @@ func (pt Type) Name() string {
return "Conda"
case TypeContainer:
return "Container"
case TypeCran:
return "CRAN"
case TypeDebian:
return "Debian"
case TypeGeneric:
@@ -139,6 +143,8 @@ func (pt Type) SVGName() string {
return "gitea-conda"
case TypeContainer:
return "octicon-container"
case TypeCran:
return "gitea-cran"
case TypeDebian:
return "gitea-debian"
case TypeGeneric:
+18 -35
View File
@@ -102,45 +102,28 @@ func (p *Permission) CanWriteIssuesOrPulls(isPull bool) bool {
return p.CanWrite(unit.TypeIssues)
}
// ColorFormat writes a colored string for these Permissions
func (p *Permission) ColorFormat(s fmt.State) {
noColor := log.ColorBytes(log.Reset)
func (p *Permission) LogString() string {
format := "<Permission AccessMode=%s, %d Units, %d UnitsMode(s): [ "
args := []any{p.AccessMode.String(), len(p.Units), len(p.UnitsMode)}
format := "perm_model.AccessMode: %-v, %d Units, %d UnitsMode(s): [ "
args := []interface{}{
p.AccessMode,
log.NewColoredValueBytes(len(p.Units), &noColor),
log.NewColoredValueBytes(len(p.UnitsMode), &noColor),
}
if s.Flag('+') {
for i, unit := range p.Units {
config := ""
if unit.Config != nil {
configBytes, err := unit.Config.ToDB()
config = string(configBytes)
if err != nil {
config = err.Error()
}
for i, unit := range p.Units {
config := ""
if unit.Config != nil {
configBytes, err := unit.Config.ToDB()
config = string(configBytes)
if err != nil {
config = err.Error()
}
format += "\nUnits[%d]: ID: %d RepoID: %d Type: %-v Config: %s"
args = append(args,
log.NewColoredValueBytes(i, &noColor),
log.NewColoredIDValue(unit.ID),
log.NewColoredIDValue(unit.RepoID),
unit.Type,
config)
}
for key, value := range p.UnitsMode {
format += "\nUnitMode[%-v]: %-v"
args = append(args,
key,
value)
}
} else {
format += "..."
format += "\nUnits[%d]: ID: %d RepoID: %d Type: %s Config: %s"
args = append(args, i, unit.ID, unit.RepoID, unit.Type.LogString(), config)
}
format += " ]"
log.ColorFprintf(s, format, args...)
for key, value := range p.UnitsMode {
format += "\nUnitMode[%-v]: %-v"
args = append(args, key.LogString(), value.LogString())
}
format += " ]>"
return fmt.Sprintf(format, args...)
}
// GetUserRepoPermission returns the user permissions to the repository
+2 -7
View File
@@ -5,8 +5,6 @@ package perm
import (
"fmt"
"code.gitea.io/gitea/modules/log"
)
// AccessMode specifies the users access mode
@@ -40,11 +38,8 @@ func (mode AccessMode) String() string {
}
}
// ColorFormat provides a ColorFormatted version of this AccessMode
func (mode AccessMode) ColorFormat(s fmt.State) {
log.ColorFprintf(s, "%d:%s",
log.NewColoredIDValue(mode),
mode)
func (mode AccessMode) LogString() string {
return fmt.Sprintf("<AccessMode:%d:%s>", mode, mode.String())
}
// ParseAccessMode returns corresponding access mode to given permission string.
+11 -11
View File
@@ -198,19 +198,11 @@ func (repo *Repository) SanitizedOriginalURL() string {
return u.String()
}
// ColorFormat returns a colored string to represent this repo
func (repo *Repository) ColorFormat(s fmt.State) {
func (repo *Repository) LogString() string {
if repo == nil {
log.ColorFprintf(s, "%d:%s/%s",
log.NewColoredIDValue(0),
"<nil>",
"<nil>")
return
return "<Repository nil>"
}
log.ColorFprintf(s, "%d:%s/%s",
log.NewColoredIDValue(repo.ID),
repo.OwnerName,
repo.Name)
return fmt.Sprintf("<Repository %d:%s/%s>", repo.ID, repo.OwnerName, repo.Name)
}
// IsBeingMigrated indicates that repository is being migrated
@@ -881,3 +873,11 @@ func FixNullArchivedRepository(ctx context.Context) (int64, error) {
IsArchived: false,
})
}
// UpdateRepositoryOwnerName updates the owner name of all repositories owned by the user
func UpdateRepositoryOwnerName(ctx context.Context, oldUserName, newUserName string) error {
if _, err := db.GetEngine(ctx).Exec("UPDATE `repository` SET owner_name=? WHERE owner_name=?", newUserName, oldUserName); err != nil {
return fmt.Errorf("change repo owner name: %w", err)
}
return nil
}
+25 -20
View File
@@ -253,16 +253,7 @@ func AddTopic(repoID int64, topicName string) (*Topic, error) {
return nil, err
}
topicNames := make([]string, 0, 25)
if err := sess.Select("name").Table("topic").
Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id").
Where("repo_topic.repo_id = ?", repoID).Desc("topic.repo_count").Find(&topicNames); err != nil {
return nil, err
}
if _, err := sess.ID(repoID).Cols("topics").Update(&Repository{
Topics: topicNames,
}); err != nil {
if err = syncTopicsInRepository(sess, repoID); err != nil {
return nil, err
}
@@ -281,6 +272,11 @@ func DeleteTopic(repoID int64, topicName string) (*Topic, error) {
}
err = removeTopicFromRepo(db.DefaultContext, repoID, topic)
if err != nil {
return nil, err
}
err = syncTopicsInRepository(db.GetEngine(db.DefaultContext), repoID)
return topic, err
}
@@ -347,16 +343,7 @@ func SaveTopics(repoID int64, topicNames ...string) error {
}
}
topicNames = make([]string, 0, 25)
if err := sess.Table("topic").Cols("name").
Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id").
Where("repo_topic.repo_id = ?", repoID).Desc("topic.repo_count").Find(&topicNames); err != nil {
return err
}
if _, err := sess.ID(repoID).Cols("topics").Update(&Repository{
Topics: topicNames,
}); err != nil {
if err := syncTopicsInRepository(sess, repoID); err != nil {
return err
}
@@ -370,5 +357,23 @@ func GenerateTopics(ctx context.Context, templateRepo, generateRepo *Repository)
return err
}
}
return syncTopicsInRepository(db.GetEngine(ctx), generateRepo.ID)
}
// syncTopicsInRepository makes sure topics in the topics table are copied into the topics field of the repository
func syncTopicsInRepository(sess db.Engine, repoID int64) error {
topicNames := make([]string, 0, 25)
if err := sess.Table("topic").Cols("name").
Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id").
Where("repo_topic.repo_id = ?", repoID).Desc("topic.repo_count").Find(&topicNames); err != nil {
return err
}
if _, err := sess.ID(repoID).Cols("topics").Update(&Repository{
Topics: topicNames,
}); err != nil {
return err
}
return nil
}
+2 -5
View File
@@ -62,11 +62,8 @@ func (u Type) String() string {
return fmt.Sprintf("Unknown Type %d", u)
}
// ColorFormat provides a ColorFormatted version of this Type
func (u Type) ColorFormat(s fmt.State) {
log.ColorFprintf(s, "%d:%s",
log.NewColoredIDValue(u),
u)
func (u Type) LogString() string {
return fmt.Sprintf("<UnitType:%d:%s>", u, u.String())
}
var (
+31 -7
View File
@@ -9,13 +9,6 @@ import (
"code.gitea.io/gitea/modules/util"
)
// ____ ___
// | | \______ ___________
// | | / ___// __ \_ __ \
// | | /\___ \\ ___/| | \/
// |______//____ >\___ >__|
// \/ \/
// ErrUserAlreadyExist represents a "user already exists" error.
type ErrUserAlreadyExist struct {
Name string
@@ -99,3 +92,34 @@ func (err ErrUserInactive) Error() string {
func (err ErrUserInactive) Unwrap() error {
return util.ErrPermissionDenied
}
// ErrUserIsNotLocal represents a "ErrUserIsNotLocal" kind of error.
type ErrUserIsNotLocal struct {
UID int64
Name string
}
func (err ErrUserIsNotLocal) Error() string {
return fmt.Sprintf("user is not local type [uid: %d, name: %s]", err.UID, err.Name)
}
// IsErrUserIsNotLocal
func IsErrUserIsNotLocal(err error) bool {
_, ok := err.(ErrUserIsNotLocal)
return ok
}
type ErrUsernameNotChanged struct {
UID int64
Name string
}
func (err ErrUsernameNotChanged) Error() string {
return fmt.Sprintf("username hasn't been changed[uid: %d, name: %s]", err.UID, err.Name)
}
// IsErrUsernameNotChanged
func IsErrUsernameNotChanged(err error) bool {
_, ok := err.(ErrUsernameNotChanged)
return ok
}
+3 -54
View File
@@ -9,7 +9,6 @@ import (
"encoding/hex"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"time"
@@ -152,17 +151,11 @@ type SearchOrganizationsOptions struct {
All bool
}
// ColorFormat writes a colored string to identify this struct
func (u *User) ColorFormat(s fmt.State) {
func (u *User) LogString() string {
if u == nil {
log.ColorFprintf(s, "%d:%s",
log.NewColoredIDValue(0),
log.NewColoredValue("<nil>"))
return
return "<User nil>"
}
log.ColorFprintf(s, "%d:%s",
log.NewColoredIDValue(u.ID),
log.NewColoredValue(u.Name))
return fmt.Sprintf("<User %d:%s>", u.ID, u.Name)
}
// BeforeUpdate is invoked from XORM before updating this object.
@@ -756,50 +749,6 @@ func VerifyUserActiveCode(code string) (user *User) {
return nil
}
// ChangeUserName changes all corresponding setting from old user name to new one.
func ChangeUserName(ctx context.Context, u *User, newUserName string) (err error) {
oldUserName := u.Name
if err = IsUsableUsername(newUserName); err != nil {
return err
}
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
defer committer.Close()
isExist, err := IsUserExist(ctx, 0, newUserName)
if err != nil {
return err
} else if isExist {
return ErrUserAlreadyExist{newUserName}
}
if _, err = db.GetEngine(ctx).Exec("UPDATE `repository` SET owner_name=? WHERE owner_name=?", newUserName, oldUserName); err != nil {
return fmt.Errorf("Change repo owner name: %w", err)
}
// Do not fail if directory does not exist
if err = util.Rename(UserPath(oldUserName), UserPath(newUserName)); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("Rename user directory: %w", err)
}
if err = NewUserRedirect(ctx, u.ID, oldUserName, newUserName); err != nil {
return err
}
if err = committer.Commit(); err != nil {
if err2 := util.Rename(UserPath(newUserName), UserPath(oldUserName)); err2 != nil && !os.IsNotExist(err2) {
log.Critical("Unable to rollback directory change during failed username change from: %s to: %s. DB Error: %v. Filesystem Error: %v", oldUserName, newUserName, err, err2)
return fmt.Errorf("failed to rollback directory change during failed username change from: %s to: %s. DB Error: %w. Filesystem Error: %v", oldUserName, newUserName, err, err2)
}
return err
}
return nil
}
// checkDupEmail checks whether there are the same email with the user
func checkDupEmail(ctx context.Context, u *User) error {
u.Email = strings.ToLower(u.Email)