github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/patcher/main.go (about) 1 package main 2 3 import ( 4 "bufio" 5 "database/sql" 6 "encoding/json" 7 "fmt" 8 "io/ioutil" 9 "log" 10 "os" 11 "runtime/debug" 12 "strconv" 13 14 c "github.com/Azareal/Gosora/common" 15 qgen "github.com/Azareal/Gosora/query_gen" 16 _ "github.com/go-sql-driver/mysql" 17 ) 18 19 var patches = make(map[int]func(*bufio.Scanner) error) 20 21 func addPatch(index int, handle func(*bufio.Scanner) error) { 22 patches[index] = handle 23 } 24 25 func main() { 26 scanner := bufio.NewScanner(os.Stdin) 27 28 // Capture panics instead of closing the window at a superhuman speed before the user can read the message on Windows 29 defer func() { 30 if r := recover(); r != nil { 31 fmt.Println(r) 32 debug.PrintStack() 33 pressAnyKey(scanner) 34 log.Fatal("") 35 return 36 } 37 }() 38 39 log.Print("Loading the configuration data") 40 err := c.LoadConfig() 41 if err != nil { 42 log.Fatal(err) 43 } 44 45 log.Print("Processing configuration data") 46 err = c.ProcessConfig() 47 if err != nil { 48 log.Fatal(err) 49 } 50 51 if c.DbConfig.Adapter != "mysql" && c.DbConfig.Adapter != "" { 52 log.Fatal("Only MySQL is supported for upgrades right now, please wait for a newer build of the patcher") 53 } 54 55 err = prepMySQL() 56 if err != nil { 57 log.Fatal(err) 58 } 59 60 err = patcher(scanner) 61 if err != nil { 62 log.Fatal(err) 63 } 64 } 65 66 func pressAnyKey(scanner *bufio.Scanner) { 67 fmt.Println("Please press enter to exit...") 68 for scanner.Scan() { 69 _ = scanner.Text() 70 return 71 } 72 } 73 74 func prepMySQL() error { 75 return qgen.Builder.Init("mysql", map[string]string{ 76 "host": c.DbConfig.Host, 77 "port": c.DbConfig.Port, 78 "name": c.DbConfig.Dbname, 79 "username": c.DbConfig.Username, 80 "password": c.DbConfig.Password, 81 "collation": "utf8mb4_general_ci", 82 }) 83 } 84 85 type SchemaFile struct { 86 DBVersion string // Current version of the database schema 87 DynamicFileVersion string 88 MinGoVersion string // TODO: Minimum version of Go needed to install this version 89 MinVersion string // TODO: Minimum version of Gosora to jump to this version, might be tricky as we don't store this in the schema file, maybe store it in the database 90 } 91 92 func loadSchema() (schemaFile SchemaFile, err error) { 93 fmt.Println("Loading the schema file") 94 data, err := ioutil.ReadFile("./schema/lastSchema.json") 95 if err != nil { 96 return schemaFile, err 97 } 98 err = json.Unmarshal(data, &schemaFile) 99 return schemaFile, err 100 } 101 102 func patcher(scanner *bufio.Scanner) error { 103 var dbVersion int 104 err := qgen.NewAcc().Select("updates").Columns("dbVersion").QueryRow().Scan(&dbVersion) 105 if err == sql.ErrNoRows { 106 schemaFile, err := loadSchema() 107 if err != nil { 108 return err 109 } 110 dbVersion, err = strconv.Atoi(schemaFile.DBVersion) 111 if err != nil { 112 return err 113 } 114 } else if err != nil { 115 return err 116 } 117 118 fmt.Println("Applying the patches") 119 var pslice = make([]func(*bufio.Scanner) error, len(patches)) 120 for i := 0; i < len(patches); i++ { 121 pslice[i] = patches[i] 122 } 123 124 // Run the queued up patches 125 var patched int 126 for index, patch := range pslice { 127 if dbVersion > index { 128 continue 129 } 130 err := patch(scanner) 131 if err != nil { 132 fmt.Println("Failed to apply patch " + strconv.Itoa(index+1)) 133 return err 134 } 135 fmt.Println("Applied patch " + strconv.Itoa(index+1)) 136 patched++ 137 } 138 139 if patched > 0 { 140 _, err := qgen.NewAcc().Update("updates").Set("dbVersion = ?").Exec(len(pslice)) 141 if err != nil { 142 return err 143 } 144 } else { 145 fmt.Println("No new patches found.") 146 } 147 148 return nil 149 }