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  }