From 66cead0cdccbfc8193b25ede07706c3813e6c404 Mon Sep 17 00:00:00 2001 From: Masudur Rahman Date: Thu, 17 Oct 2019 00:27:16 +0600 Subject: [PATCH 01/10] Fix user avatar name Signed-off-by: Masudur Rahman --- models/user.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/models/user.go b/models/user.go index 0454158de6863..f2487dda25f20 100644 --- a/models/user.go +++ b/models/user.go @@ -521,7 +521,11 @@ func (u *User) UploadAvatar(data []byte) error { } u.UseCustomAvatar = true - u.Avatar = fmt.Sprintf("%x", md5.Sum(data)) + // Different users can upload same image as avatar + // If we prefix it with u.ID, it will be separated + // Otherwise, if any of the users delete his avatar + // Other users will lose their avatars too. + u.Avatar = fmt.Sprintf("%d-%x", u.ID, md5.Sum(data)) if err = updateUser(sess, u); err != nil { return fmt.Errorf("updateUser: %v", err) } From e958c75777b647d1fae828d0e933dc1f19d7b644 Mon Sep 17 00:00:00 2001 From: Masudur Rahman Date: Thu, 17 Oct 2019 20:19:29 +0600 Subject: [PATCH 02/10] Add migration renameExistingUserAvatarName --- models/migrations/migrations.go | 2 + models/migrations/v115.go | 73 +++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 models/migrations/v115.go diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 923b5f5759c10..00d836695f190 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -284,6 +284,8 @@ var migrations = []Migration{ NewMigration("new feature: change target branch of pull requests", featureChangeTargetBranch), // v114 -> v115 NewMigration("Remove authentication credentials from stored URL", sanitizeOriginalURL), + // v115 -> v116 + NewMigration("add user_id prefix to existing user avatar name", renameExistingUserAvatarName), } // Migrate database to current version diff --git a/models/migrations/v115.go b/models/migrations/v115.go new file mode 100644 index 0000000000000..887e998ee3a82 --- /dev/null +++ b/models/migrations/v115.go @@ -0,0 +1,73 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "fmt" + "io" + "os" + "path/filepath" + "strconv" + "strings" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/setting" + + "xorm.io/xorm" +) + +func renameExistingUserAvatarName(x *xorm.Engine) error { + sess := x.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return err + } + + users := make([]models.User, 0) + if err := sess.Find(&users); err != nil { + return err + } + + deleteList := make([]string, 0, len(users)) + for _, user := range users { + if !strings.HasPrefix(user.Avatar, strconv.FormatInt(user.ID, 10)+"-") { + oldAvatar := user.Avatar + newAvatar := fmt.Sprintf("%d-%s", user.ID, user.Avatar) + + if _, err := os.Stat(filepath.Join(setting.AvatarUploadPath, oldAvatar)); err != nil { + continue + } + + fr, err := os.Open(filepath.Join(setting.AvatarUploadPath, oldAvatar)) + if err != nil { + return err + } + defer fr.Close() + + fw, err := os.Create(filepath.Join(setting.AvatarUploadPath, newAvatar)) + if err != nil { + return err + } + defer fw.Close() + + if _, err := io.Copy(fw, fr); err != nil { + return err + } + + user.Avatar = newAvatar + if _, err := sess.ID(user.ID).Update(&user); err != nil { + return err + } + + deleteList = append(deleteList, filepath.Join(setting.AvatarUploadPath, oldAvatar)) + } + } + for _, file := range deleteList { + if err := os.Remove(file); err != nil { + return err + } + } + return sess.Commit() +} From bb14679489f704dfd71765d2a73df8a59e86dfa2 Mon Sep 17 00:00:00 2001 From: Masudur Rahman Date: Fri, 18 Oct 2019 00:32:41 +0600 Subject: [PATCH 03/10] Use custom User table for migration --- models/migrations/v115.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/models/migrations/v115.go b/models/migrations/v115.go index 887e998ee3a82..e8bc5c92562d4 100644 --- a/models/migrations/v115.go +++ b/models/migrations/v115.go @@ -12,7 +12,6 @@ import ( "strconv" "strings" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/setting" "xorm.io/xorm" @@ -25,7 +24,12 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { return err } - users := make([]models.User, 0) + type User struct { + ID int64 `xorm:"pk autoincr"` + Avatar string + } + + users := make([]User, 0) if err := sess.Find(&users); err != nil { return err } From 7947e9c29d418de88aa70ac23da99a995296922c Mon Sep 17 00:00:00 2001 From: Masudur Rahman Date: Fri, 18 Oct 2019 03:14:03 +0600 Subject: [PATCH 04/10] Update user avatar name --- models/migrations/v115.go | 51 ++++++++++++++++++--------------------- models/user.go | 2 +- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/models/migrations/v115.go b/models/migrations/v115.go index e8bc5c92562d4..9cba4cb1bac04 100644 --- a/models/migrations/v115.go +++ b/models/migrations/v115.go @@ -5,12 +5,11 @@ package migrations import ( + "crypto/md5" "fmt" "io" "os" "path/filepath" - "strconv" - "strings" "code.gitea.io/gitea/modules/setting" @@ -36,37 +35,35 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { deleteList := make([]string, 0, len(users)) for _, user := range users { - if !strings.HasPrefix(user.Avatar, strconv.FormatInt(user.ID, 10)+"-") { - oldAvatar := user.Avatar - newAvatar := fmt.Sprintf("%d-%s", user.ID, user.Avatar) + oldAvatar := user.Avatar + newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%s", user.ID, user.Avatar)))) - if _, err := os.Stat(filepath.Join(setting.AvatarUploadPath, oldAvatar)); err != nil { - continue - } - - fr, err := os.Open(filepath.Join(setting.AvatarUploadPath, oldAvatar)) - if err != nil { - return err - } - defer fr.Close() + if _, err := os.Stat(filepath.Join(setting.AvatarUploadPath, oldAvatar)); err != nil { + continue + } - fw, err := os.Create(filepath.Join(setting.AvatarUploadPath, newAvatar)) - if err != nil { - return err - } - defer fw.Close() + fr, err := os.Open(filepath.Join(setting.AvatarUploadPath, oldAvatar)) + if err != nil { + return err + } + defer fr.Close() - if _, err := io.Copy(fw, fr); err != nil { - return err - } + fw, err := os.Create(filepath.Join(setting.AvatarUploadPath, newAvatar)) + if err != nil { + return err + } + defer fw.Close() - user.Avatar = newAvatar - if _, err := sess.ID(user.ID).Update(&user); err != nil { - return err - } + if _, err := io.Copy(fw, fr); err != nil { + return err + } - deleteList = append(deleteList, filepath.Join(setting.AvatarUploadPath, oldAvatar)) + user.Avatar = newAvatar + if _, err := sess.ID(user.ID).Update(&user); err != nil { + return err } + + deleteList = append(deleteList, filepath.Join(setting.AvatarUploadPath, oldAvatar)) } for _, file := range deleteList { if err := os.Remove(file); err != nil { diff --git a/models/user.go b/models/user.go index f2487dda25f20..e832c2ed519b8 100644 --- a/models/user.go +++ b/models/user.go @@ -525,7 +525,7 @@ func (u *User) UploadAvatar(data []byte) error { // If we prefix it with u.ID, it will be separated // Otherwise, if any of the users delete his avatar // Other users will lose their avatars too. - u.Avatar = fmt.Sprintf("%d-%x", u.ID, md5.Sum(data)) + u.Avatar = fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", u.ID, md5.Sum(data))))) if err = updateUser(sess, u); err != nil { return fmt.Errorf("updateUser: %v", err) } From e39cf6826184f1468c6b62c247ba57a2f4920261 Mon Sep 17 00:00:00 2001 From: Masudur Rahman Date: Fri, 18 Oct 2019 22:08:04 +0600 Subject: [PATCH 05/10] Commit session before every os.Error and also interval commit session Signed-off-by: Masudur Rahman --- models/migrations/v115.go | 44 ++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/models/migrations/v115.go b/models/migrations/v115.go index 9cba4cb1bac04..a35e5d6241c05 100644 --- a/models/migrations/v115.go +++ b/models/migrations/v115.go @@ -33,42 +33,66 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { return err } - deleteList := make([]string, 0, len(users)) + deleteList := make(map[string]struct{}) + sessionOpCount := 0 for _, user := range users { oldAvatar := user.Avatar newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%s", user.ID, user.Avatar)))) - if _, err := os.Stat(filepath.Join(setting.AvatarUploadPath, oldAvatar)); err != nil { continue } fr, err := os.Open(filepath.Join(setting.AvatarUploadPath, oldAvatar)) if err != nil { - return err + _ = commitSession(sess) + return fmt.Errorf("os.Open: %v", err) } defer fr.Close() fw, err := os.Create(filepath.Join(setting.AvatarUploadPath, newAvatar)) if err != nil { - return err + _ = commitSession(sess) + return fmt.Errorf("os.Create: %v", err) } defer fw.Close() if _, err := io.Copy(fw, fr); err != nil { - return err + _ = commitSession(sess) + return fmt.Errorf("io.Copy: %v", err) } user.Avatar = newAvatar if _, err := sess.ID(user.ID).Update(&user); err != nil { - return err + return fmt.Errorf("user table update: %v", err) } - deleteList = append(deleteList, filepath.Join(setting.AvatarUploadPath, oldAvatar)) + deleteList[filepath.Join(setting.AvatarUploadPath, oldAvatar)] = struct{}{} + + if sessionOpCount++; sessionOpCount >= 100 { + if err := commitSession(sess); err != nil { + return err + } + sessionOpCount = 0 + if err := sess.Begin(); err != nil { + return err + } + } + } + if err := commitSession(sess); err != nil { + return err } - for _, file := range deleteList { + for file := range deleteList { if err := os.Remove(file); err != nil { - return err + return fmt.Errorf("os.Remove: %v", err) } } - return sess.Commit() + return nil +} + +func commitSession(sess *xorm.Session) error { + if err := sess.Commit(); err != nil { + _ = sess.Rollback() + return fmt.Errorf("db update: %v", err) + } + return nil } From 819db1c4183ddd71956a732a04e5a587ae2082ac Mon Sep 17 00:00:00 2001 From: Masudur Rahman Date: Sat, 19 Oct 2019 17:25:54 +0600 Subject: [PATCH 06/10] Process updating user in batches Signed-off-by: Masudur Rahman --- models/migrations/v115.go | 99 ++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 47 deletions(-) diff --git a/models/migrations/v115.go b/models/migrations/v115.go index a35e5d6241c05..bf53dd9e02534 100644 --- a/models/migrations/v115.go +++ b/models/migrations/v115.go @@ -11,6 +11,7 @@ import ( "os" "path/filepath" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "xorm.io/xorm" @@ -19,71 +20,75 @@ import ( func renameExistingUserAvatarName(x *xorm.Engine) error { sess := x.NewSession() defer sess.Close() - if err := sess.Begin(); err != nil { - return err - } type User struct { ID int64 `xorm:"pk autoincr"` Avatar string } - - users := make([]User, 0) - if err := sess.Find(&users); err != nil { - return err - } - deleteList := make(map[string]struct{}) - sessionOpCount := 0 - for _, user := range users { - oldAvatar := user.Avatar - newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%s", user.ID, user.Avatar)))) - if _, err := os.Stat(filepath.Join(setting.AvatarUploadPath, oldAvatar)); err != nil { - continue + start := 0 + for { + if err := sess.Begin(); err != nil { + return fmt.Errorf("session.Begin: %v", err) } - - fr, err := os.Open(filepath.Join(setting.AvatarUploadPath, oldAvatar)) - if err != nil { - _ = commitSession(sess) - return fmt.Errorf("os.Open: %v", err) + users := make([]User, 0, 50) + if err := sess.Table("user").Asc("id").Limit(50, start).Find(&users); err != nil { + return fmt.Errorf("select users from id [%d]: %v", start, err) } - defer fr.Close() - - fw, err := os.Create(filepath.Join(setting.AvatarUploadPath, newAvatar)) - if err != nil { - _ = commitSession(sess) - return fmt.Errorf("os.Create: %v", err) + if len(users) == 0 { + break } - defer fw.Close() + log.Info("select users [%d - %d]", start, start+len(users)) + start += 50 - if _, err := io.Copy(fw, fr); err != nil { - _ = commitSession(sess) - return fmt.Errorf("io.Copy: %v", err) - } + for _, user := range users { + oldAvatar := user.Avatar + newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%s", user.ID, user.Avatar)))) + if _, err := os.Stat(filepath.Join(setting.AvatarUploadPath, oldAvatar)); err != nil { + log.Warn("os.Stat: %v", err) + continue + } - user.Avatar = newAvatar - if _, err := sess.ID(user.ID).Update(&user); err != nil { - return fmt.Errorf("user table update: %v", err) - } + fr, err := os.Open(filepath.Join(setting.AvatarUploadPath, oldAvatar)) + if err != nil { + if err := commitSession(sess); err != nil { + return fmt.Errorf("commit session: %v", err) + } + return fmt.Errorf("os.Open: %v", err) + } + defer fr.Close() - deleteList[filepath.Join(setting.AvatarUploadPath, oldAvatar)] = struct{}{} + fw, err := os.Create(filepath.Join(setting.AvatarUploadPath, newAvatar)) + if err != nil { + if err := commitSession(sess); err != nil { + return fmt.Errorf("commit session: %v", err) + } + return fmt.Errorf("os.Create: %v", err) + } + defer fw.Close() - if sessionOpCount++; sessionOpCount >= 100 { - if err := commitSession(sess); err != nil { - return err + if _, err := io.Copy(fw, fr); err != nil { + if err := commitSession(sess); err != nil { + return fmt.Errorf("commit session: %v", err) + } + return fmt.Errorf("io.Copy: %v", err) } - sessionOpCount = 0 - if err := sess.Begin(); err != nil { - return err + + user.Avatar = newAvatar + if _, err := sess.ID(user.ID).Update(&user); err != nil { + return fmt.Errorf("user table update: %v", err) } + + deleteList[filepath.Join(setting.AvatarUploadPath, oldAvatar)] = struct{}{} + } + if err := commitSession(sess); err != nil { + return fmt.Errorf("commit session: %v", err) } } - if err := commitSession(sess); err != nil { - return err - } + for file := range deleteList { if err := os.Remove(file); err != nil { - return fmt.Errorf("os.Remove: %v", err) + log.Warn("os.Remove: %v", err) } } return nil @@ -92,7 +97,7 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { func commitSession(sess *xorm.Session) error { if err := sess.Commit(); err != nil { _ = sess.Rollback() - return fmt.Errorf("db update: %v", err) + return err } return nil } From d096b9bc4e2fd11efc0a8531ce7a2c4ab19ff8c6 Mon Sep 17 00:00:00 2001 From: Masudur Rahman Date: Sat, 19 Oct 2019 19:25:05 +0600 Subject: [PATCH 07/10] Move copying avatar part to a function Signed-off-by: Masudur Rahman --- models/migrations/v115.go | 63 ++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/models/migrations/v115.go b/models/migrations/v115.go index bf53dd9e02534..df5ecf38cde1a 100644 --- a/models/migrations/v115.go +++ b/models/migrations/v115.go @@ -22,8 +22,9 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { defer sess.Close() type User struct { - ID int64 `xorm:"pk autoincr"` - Avatar string + ID int64 `xorm:"pk autoincr"` + LowerName string `xorm:"UNIQUE NOT NULL"` + Avatar string } deleteList := make(map[string]struct{}) start := 0 @@ -31,13 +32,14 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { if err := sess.Begin(); err != nil { return fmt.Errorf("session.Begin: %v", err) } - users := make([]User, 0, 50) + users := make([]*User, 0, 50) if err := sess.Table("user").Asc("id").Limit(50, start).Find(&users); err != nil { return fmt.Errorf("select users from id [%d]: %v", start, err) } if len(users) == 0 { break } + log.Info("select users [%d - %d]", start, start+len(users)) start += 50 @@ -45,43 +47,25 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { oldAvatar := user.Avatar newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%s", user.ID, user.Avatar)))) if _, err := os.Stat(filepath.Join(setting.AvatarUploadPath, oldAvatar)); err != nil { - log.Warn("os.Stat: %v", err) + log.Warn("[user: %s] os.Stat: %v", user.LowerName, err) + // avatar doesn't exist in the storage + // no need to move avatar and update database + // we can just skip this continue } - fr, err := os.Open(filepath.Join(setting.AvatarUploadPath, oldAvatar)) - if err != nil { - if err := commitSession(sess); err != nil { - return fmt.Errorf("commit session: %v", err) - } - return fmt.Errorf("os.Open: %v", err) - } - defer fr.Close() - - fw, err := os.Create(filepath.Join(setting.AvatarUploadPath, newAvatar)) - if err != nil { - if err := commitSession(sess); err != nil { - return fmt.Errorf("commit session: %v", err) - } - return fmt.Errorf("os.Create: %v", err) - } - defer fw.Close() - - if _, err := io.Copy(fw, fr); err != nil { - if err := commitSession(sess); err != nil { - return fmt.Errorf("commit session: %v", err) - } - return fmt.Errorf("io.Copy: %v", err) + if err := copyAvatar(oldAvatar, newAvatar); err != nil { + return fmt.Errorf("[user: %s] %v", user.LowerName, err) } user.Avatar = newAvatar - if _, err := sess.ID(user.ID).Update(&user); err != nil { - return fmt.Errorf("user table update: %v", err) + if _, err := sess.ID(user.ID).Update(user); err != nil { + return fmt.Errorf("[user: %s] user table update: %v", user.LowerName, err) } deleteList[filepath.Join(setting.AvatarUploadPath, oldAvatar)] = struct{}{} } - if err := commitSession(sess); err != nil { + if err := sess.Commit(); err != nil { return fmt.Errorf("commit session: %v", err) } } @@ -94,10 +78,21 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { return nil } -func commitSession(sess *xorm.Session) error { - if err := sess.Commit(); err != nil { - _ = sess.Rollback() - return err +func copyAvatar(oldAvatar, newAvatar string) error { + fr, err := os.Open(filepath.Join(setting.AvatarUploadPath, oldAvatar)) + if err != nil { + return fmt.Errorf("os.Open: %v", err) + } + defer fr.Close() + + fw, err := os.Create(filepath.Join(setting.AvatarUploadPath, newAvatar)) + if err != nil { + return fmt.Errorf("os.Create: %v", err) + } + defer fw.Close() + + if _, err := io.Copy(fw, fr); err != nil { + return fmt.Errorf("io.Copy: %v", err) } return nil } From 717add45000e773e6ed8a8db3e6e6d014bcf48c0 Mon Sep 17 00:00:00 2001 From: Masudur Rahman Date: Tue, 19 Nov 2019 01:02:42 +0600 Subject: [PATCH 08/10] Rollback session before returning error --- models/migrations/v115.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/models/migrations/v115.go b/models/migrations/v115.go index df5ecf38cde1a..e51891153fa3d 100644 --- a/models/migrations/v115.go +++ b/models/migrations/v115.go @@ -37,6 +37,7 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { return fmt.Errorf("select users from id [%d]: %v", start, err) } if len(users) == 0 { + _ = sess.Rollback() break } @@ -55,17 +56,20 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { } if err := copyAvatar(oldAvatar, newAvatar); err != nil { + _ = sess.Rollback() return fmt.Errorf("[user: %s] %v", user.LowerName, err) } user.Avatar = newAvatar - if _, err := sess.ID(user.ID).Update(user); err != nil { + if _, err := sess.ID(user.ID).Cols("avatar").Update(user); err != nil { + _ = sess.Rollback() return fmt.Errorf("[user: %s] user table update: %v", user.LowerName, err) } deleteList[filepath.Join(setting.AvatarUploadPath, oldAvatar)] = struct{}{} } if err := sess.Commit(); err != nil { + _ = sess.Rollback() return fmt.Errorf("commit session: %v", err) } } From ee97b6905987630faa2d768fb6281af569e67fa0 Mon Sep 17 00:00:00 2001 From: Masudur Rahman Date: Thu, 26 Dec 2019 21:19:44 +0600 Subject: [PATCH 09/10] Generate newAvatar from the avatar file Signed-off-by: Masudur Rahman --- models/migrations/v115.go | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/models/migrations/v115.go b/models/migrations/v115.go index e51891153fa3d..f839cbb849dce 100644 --- a/models/migrations/v115.go +++ b/models/migrations/v115.go @@ -7,7 +7,7 @@ package migrations import ( "crypto/md5" "fmt" - "io" + "io/ioutil" "os" "path/filepath" @@ -46,7 +46,7 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { for _, user := range users { oldAvatar := user.Avatar - newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%s", user.ID, user.Avatar)))) + if _, err := os.Stat(filepath.Join(setting.AvatarUploadPath, oldAvatar)); err != nil { log.Warn("[user: %s] os.Stat: %v", user.LowerName, err) // avatar doesn't exist in the storage @@ -55,7 +55,8 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { continue } - if err := copyAvatar(oldAvatar, newAvatar); err != nil { + newAvatar, err := copyOldAvatarToNewLocation(user.ID, oldAvatar) + if err != nil { _ = sess.Rollback() return fmt.Errorf("[user: %s] %v", user.LowerName, err) } @@ -82,21 +83,25 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { return nil } -func copyAvatar(oldAvatar, newAvatar string) error { +// copyOldAvatarToNewLocation copies oldAvatar to newAvatarLocation +// and returns newAvatar location +func copyOldAvatarToNewLocation(userID int64, oldAvatar string) (string, error) { fr, err := os.Open(filepath.Join(setting.AvatarUploadPath, oldAvatar)) if err != nil { - return fmt.Errorf("os.Open: %v", err) + return "", fmt.Errorf("os.Open: %v", err) } defer fr.Close() - fw, err := os.Create(filepath.Join(setting.AvatarUploadPath, newAvatar)) + data, err := ioutil.ReadAll(fr) if err != nil { - return fmt.Errorf("os.Create: %v", err) + return "", fmt.Errorf("ioutil.ReadAll: %v", err) } - defer fw.Close() - if _, err := io.Copy(fw, fr); err != nil { - return fmt.Errorf("io.Copy: %v", err) + newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", userID, md5.Sum(data))))) + + if err := ioutil.WriteFile(filepath.Join(setting.AvatarUploadPath, newAvatar), data, 0666); err != nil { + return "", fmt.Errorf("ioutil.WriteFile: %v", err) } - return nil + + return newAvatar, nil } From f87ddd2d9fd32d95957e0f2ef91a70f81ab65f69 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Fri, 27 Dec 2019 17:40:52 +0000 Subject: [PATCH 10/10] Cope with partial rerun of migration --- models/migrations/v115.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/models/migrations/v115.go b/models/migrations/v115.go index f839cbb849dce..f1603b797620f 100644 --- a/models/migrations/v115.go +++ b/models/migrations/v115.go @@ -59,6 +59,8 @@ func renameExistingUserAvatarName(x *xorm.Engine) error { if err != nil { _ = sess.Rollback() return fmt.Errorf("[user: %s] %v", user.LowerName, err) + } else if newAvatar == oldAvatar { + continue } user.Avatar = newAvatar @@ -98,6 +100,9 @@ func copyOldAvatarToNewLocation(userID int64, oldAvatar string) (string, error) } newAvatar := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%d-%x", userID, md5.Sum(data))))) + if newAvatar == oldAvatar { + return newAvatar, nil + } if err := ioutil.WriteFile(filepath.Join(setting.AvatarUploadPath, newAvatar), data, 0666); err != nil { return "", fmt.Errorf("ioutil.WriteFile: %v", err)