From f37cd9672cb447cb820e2da5144a25d5d6b654d7 Mon Sep 17 00:00:00 2001 From: Joe Chen Date: Sat, 26 Mar 2022 15:10:39 +0800 Subject: [PATCH] restore: clean up leftover and invalid chars (#6875) --- internal/cmd/restore.go | 31 +++++++++++++++++++------------ internal/db/backup.go | 6 +++++- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/internal/cmd/restore.go b/internal/cmd/restore.go index 1b6cdf2c1..4c4b16615 100644 --- a/internal/cmd/restore.go +++ b/internal/cmd/restore.go @@ -11,13 +11,13 @@ import ( "github.com/pkg/errors" "github.com/unknwon/cae/zip" - "github.com/unknwon/com" "github.com/urfave/cli" "gopkg.in/ini.v1" log "unknwon.dev/clog/v2" "gogs.io/gogs/internal/conf" "gogs.io/gogs/internal/db" + "gogs.io/gogs/internal/osutil" "gogs.io/gogs/internal/semverutil" ) @@ -49,20 +49,27 @@ func runRestore(c *cli.Context) error { zip.Verbose = c.Bool("verbose") tmpDir := c.String("tempdir") - if !com.IsExist(tmpDir) { + if !osutil.IsDir(tmpDir) { log.Fatal("'--tempdir' does not exist: %s", tmpDir) } + archivePath := path.Join(tmpDir, archiveRootDir) - log.Info("Restore backup from: %s", c.String("from")) - if err := zip.ExtractTo(c.String("from"), tmpDir); err != nil { + // Make sure there was no leftover and also clean up afterwards + err := os.RemoveAll(archivePath) + if err != nil { + log.Fatal("Failed to clean up previous leftover in %q: %v", archivePath, err) + } + defer func() { _ = os.RemoveAll(archivePath) }() + + log.Info("Restoring backup from: %s", c.String("from")) + err = zip.ExtractTo(c.String("from"), tmpDir) + if err != nil { log.Fatal("Failed to extract backup archive: %v", err) } - archivePath := path.Join(tmpDir, archiveRootDir) - defer func() { _ = os.RemoveAll(archivePath) }() // Check backup version metaFile := filepath.Join(archivePath, "metadata.ini") - if !com.IsExist(metaFile) { + if !osutil.IsFile(metaFile) { log.Fatal("File 'metadata.ini' is missing") } metadata, err := ini.Load(metaFile) @@ -88,7 +95,7 @@ func runRestore(c *cli.Context) error { var customConf string if c.IsSet("config") { customConf = c.String("config") - } else if !com.IsExist(configFile) { + } else if !osutil.IsFile(configFile) { log.Fatal("'--config' is not specified and custom config file is not found in backup") } else { customConf = configFile @@ -113,7 +120,7 @@ func runRestore(c *cli.Context) error { // Custom files if !c.Bool("database-only") { - if com.IsExist(conf.CustomDir()) { + if osutil.IsDir(conf.CustomDir()) { if err = os.Rename(conf.CustomDir(), conf.CustomDir()+".bak"); err != nil { log.Fatal("Failed to backup current 'custom': %v", err) } @@ -129,12 +136,12 @@ func runRestore(c *cli.Context) error { for _, dir := range []string{"attachments", "avatars", "repo-avatars"} { // Skip if backup archive does not have corresponding data srcPath := filepath.Join(archivePath, "data", dir) - if !com.IsDir(srcPath) { + if !osutil.IsDir(srcPath) { continue } dirPath := filepath.Join(conf.Server.AppDataPath, dir) - if com.IsExist(dirPath) { + if osutil.IsDir(dirPath) { if err = os.Rename(dirPath, dirPath+".bak"); err != nil { log.Fatal("Failed to backup current 'data': %v", err) } @@ -147,7 +154,7 @@ func runRestore(c *cli.Context) error { // Repositories reposPath := filepath.Join(archivePath, "repositories.zip") - if !c.Bool("exclude-repos") && !c.Bool("database-only") && com.IsExist(reposPath) { + if !c.Bool("exclude-repos") && !c.Bool("database-only") && osutil.IsDir(reposPath) { if err := zip.ExtractTo(reposPath, filepath.Dir(conf.Repository.Root)); err != nil { log.Fatal("Failed to extract 'repositories.zip': %v", err) } diff --git a/internal/db/backup.go b/internal/db/backup.go index f4dec721c..e03d78c1c 100644 --- a/internal/db/backup.go +++ b/internal/db/backup.go @@ -2,6 +2,7 @@ package db import ( "bufio" + "bytes" "fmt" "io" "os" @@ -176,8 +177,11 @@ func importTable(db *gorm.DB, table interface{}, r io.Reader) error { scanner := bufio.NewScanner(r) for scanner.Scan() { + // PostgreSQL does not like the null characters (U+0000) + cleaned := bytes.ReplaceAll(scanner.Bytes(), []byte("\\u0000"), []byte("")) + elem := reflect.New(reflect.TypeOf(table).Elem()).Interface() - err = jsoniter.Unmarshal(scanner.Bytes(), elem) + err = jsoniter.Unmarshal(cleaned, elem) if err != nil { return errors.Wrap(err, "unmarshal JSON to struct") }