[add] restore command
This commit is contained in:
parent
c913a62778
commit
e43bc0b612
3 changed files with 219 additions and 7 deletions
19
cmd/dump.go
19
cmd/dump.go
|
|
@ -2,6 +2,7 @@ package cmd
|
|||
|
||||
import (
|
||||
"archive/zip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
|
@ -49,6 +50,12 @@ var dumpCmd = &cobra.Command{
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
_, err = os.Stat(output)
|
||||
if !errors.Is(err, os.ErrNotExist) {
|
||||
fmt.Println(color.RedString("%s exists", output))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Load model
|
||||
err = engine.Load(config.Conf)
|
||||
if err != nil {
|
||||
|
|
@ -57,10 +64,8 @@ var dumpCmd = &cobra.Command{
|
|||
}
|
||||
|
||||
if dumpModel != "" {
|
||||
mod, has := gou.Models[dumpModel]
|
||||
if has {
|
||||
mod.Migrate(true)
|
||||
}
|
||||
fmt.Println(color.YellowString(L("Not supported yet")))
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -100,9 +105,9 @@ var dumpCmd = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
dumpCmd.PersistentFlags().StringVarP(&dumpModel, "name", "n", "", L("Model name"))
|
||||
}
|
||||
// func init() {
|
||||
// // dumpCmd.PersistentFlags().StringVarP(&dumpModel, "name", "n", "", L("Model name"))
|
||||
// }
|
||||
|
||||
// gzipfiles
|
||||
func zipfiles(files []string, output string, process func(file string)) error {
|
||||
|
|
|
|||
206
cmd/restore.go
Normal file
206
cmd/restore.go
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/engine"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
var restoreForce bool = false
|
||||
var restoreCmd = &cobra.Command{
|
||||
Use: "restore",
|
||||
Short: L("Restore the application data"),
|
||||
Long: L("Restore the application data"),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
defer func() {
|
||||
err := exception.Catch(recover())
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
}
|
||||
}()
|
||||
|
||||
if len(args) < 1 {
|
||||
fmt.Println(color.RedString(L("Not enough arguments")))
|
||||
fmt.Println(color.WhiteString(share.BUILDNAME + " help"))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
zipfile, err := filepath.Abs(args[0])
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
Boot()
|
||||
|
||||
if !restoreForce && config.Conf.Mode == "production" {
|
||||
fmt.Println(color.WhiteString(L("TRY:")), color.GreenString("%s restore --force", share.BUILDNAME))
|
||||
exception.New(L("Retore is not allowed on production mode."), 403).Throw()
|
||||
}
|
||||
|
||||
// Unzip files
|
||||
dst := unzipFile(zipfile, func(file string) {
|
||||
fmt.Printf("\r%s", strings.Repeat(" ", 80))
|
||||
fmt.Printf("\r%s", color.GreenString(L("Unzip the file: %s"), file))
|
||||
})
|
||||
|
||||
// 加载数据模型
|
||||
err = engine.Load(config.Conf)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Restore models
|
||||
restoreModels(filepath.Join(dst, "model"))
|
||||
|
||||
// Restore Data
|
||||
restoreData(filepath.Join(dst, "data"))
|
||||
|
||||
// Clean
|
||||
os.RemoveAll(dst)
|
||||
|
||||
fmt.Println(color.GreenString(L("✨DONE✨")))
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
restoreCmd.PersistentFlags().BoolVarP(&restoreForce, "force", "", false, L("Force restore"))
|
||||
}
|
||||
|
||||
func restoreData(basePath string) {
|
||||
|
||||
_, err := os.Stat(basePath)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Clean Data
|
||||
dataPath := filepath.Join(config.Conf.Root, "data")
|
||||
_, err = os.Stat(dataPath)
|
||||
if err == nil {
|
||||
os.RemoveAll(dataPath)
|
||||
}
|
||||
|
||||
err = os.Rename(basePath, dataPath)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func restoreModels(basePath string) {
|
||||
|
||||
files, err := ioutil.ReadDir(basePath)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Migrate models
|
||||
for _, mod := range gou.Models {
|
||||
fmt.Printf("\r%s", strings.Repeat(" ", 80))
|
||||
fmt.Printf(color.GreenString(L("\rUpdate schema model: %s (%s) "), mod.Name, mod.MetaData.Table.Name))
|
||||
err := mod.ForceCreateSchema()
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
|
||||
for _, file := range files {
|
||||
namer := strings.Split(file.Name(), ".")
|
||||
name := strings.Join(namer[:len(namer)-2], ".")
|
||||
if mod, has := gou.Models[name]; has {
|
||||
fmt.Printf("\r%s", strings.Repeat(" ", 80))
|
||||
fmt.Printf(color.GreenString(L("\rRestore model: %s (%s) "), mod.Name, mod.MetaData.Table.Name))
|
||||
err := mod.Import(filepath.Join(basePath, file.Name()))
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func unzipFile(file string, process func(file string)) string {
|
||||
_, err := os.Stat(file)
|
||||
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
fmt.Println(color.RedString("%s not exists", file))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dst := filepath.Join(os.TempDir(), fmt.Sprintf("%s-%s", filepath.Base(file), time.Now().Format("20060102150405")))
|
||||
os.MkdirAll(dst, 0755)
|
||||
|
||||
archive, err := zip.OpenReader(file)
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
defer archive.Close()
|
||||
|
||||
for _, f := range archive.File {
|
||||
filePath := filepath.Join(dst, f.Name)
|
||||
process(f.Name)
|
||||
|
||||
if !strings.HasPrefix(filePath, filepath.Clean(dst)+string(os.PathSeparator)) {
|
||||
fmt.Println(color.RedString(L("Fatal: invalid file path")))
|
||||
os.Exit(1)
|
||||
}
|
||||
if f.FileInfo().IsDir() {
|
||||
os.MkdirAll(filePath, os.ModePerm)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fileInArchive, err := f.Open()
|
||||
if err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(dstFile, fileInArchive); err != nil {
|
||||
fmt.Println(color.RedString(L("Fatal: %s"), err.Error()))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dstFile.Close()
|
||||
fileInArchive.Close()
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
|
@ -93,6 +93,7 @@ func init() {
|
|||
initCmd,
|
||||
serviceCmd,
|
||||
dumpCmd,
|
||||
restoreCmd,
|
||||
)
|
||||
// rootCmd.SetHelpCommand(helpCmd)
|
||||
rootCmd.PersistentFlags().StringVarP(&appPath, "app", "a", "", L("Application directory"))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue