github.com/CloudCom/goose@v0.0.0-20151110184009-e03c3249c21b/lib/goose/migration_go.go (about)

     1  package goose
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/gob"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"log"
     9  	"os"
    10  	"os/exec"
    11  	"path/filepath"
    12  	"strings"
    13  )
    14  
    15  type templateData struct {
    16  	Version    int64
    17  	Import     string
    18  	Conf       string // gob encoded DBConf
    19  	Direction  Direction
    20  	Func       string
    21  	InsertStmt string
    22  }
    23  
    24  func init() {
    25  	gob.Register(PostgresDialect{})
    26  	gob.Register(MySqlDialect{})
    27  	gob.Register(Sqlite3Dialect{})
    28  }
    29  
    30  //
    31  // Run a .go migration.
    32  //
    33  // In order to do this, we copy a modified version of the
    34  // original .go migration, and execute it via `go run` along
    35  // with a main() of our own creation.
    36  //
    37  func runGoMigration(conf *DBConf, path string, version int64, direction Direction) error {
    38  	// everything gets written to a temp dir, and zapped afterwards
    39  	d, e := ioutil.TempDir("", "goose")
    40  	if e != nil {
    41  		log.Fatal(e)
    42  	}
    43  	defer os.RemoveAll(d)
    44  
    45  	var bb bytes.Buffer
    46  	if err := gob.NewEncoder(&bb).Encode(conf); err != nil {
    47  		return err
    48  	}
    49  
    50  	// XXX: there must be a better way of making this byte array
    51  	// available to the generated code...
    52  	// but for now, print an array literal of the gob bytes
    53  	var sb bytes.Buffer
    54  	sb.WriteString("[]byte{ ")
    55  	for _, b := range bb.Bytes() {
    56  		sb.WriteString(fmt.Sprintf("0x%02x, ", b))
    57  	}
    58  	sb.WriteString("}")
    59  
    60  	td := &templateData{
    61  		Version:    version,
    62  		Import:     conf.Driver.Import,
    63  		Conf:       sb.String(),
    64  		Direction:  direction,
    65  		Func:       fmt.Sprintf("%v_%v", strings.ToTitle(direction.String()), version),
    66  		InsertStmt: conf.Driver.Dialect.insertVersionSql(),
    67  	}
    68  
    69  	main, e := writeTemplateToFile(filepath.Join(d, "goose_main.go"), goMigrationDriverTemplate, td)
    70  	if e != nil {
    71  		log.Fatal(e)
    72  	}
    73  
    74  	outpath := filepath.Join(d, filepath.Base(path))
    75  	if _, e = copyFile(outpath, path); e != nil {
    76  		log.Fatal(e)
    77  	}
    78  
    79  	cmd := exec.Command("go", "run", main, outpath)
    80  	cmd.Stdout = os.Stdout
    81  	cmd.Stderr = os.Stderr
    82  	if e = cmd.Run(); e != nil {
    83  		log.Fatal("`go run` failed: ", e)
    84  	}
    85  
    86  	return nil
    87  }