// NAME // test-mysql - check data generated from ModSQL into a MySQL database // // DESCRIPTION // // To create the database: // // mysql -p // mysql> create database modsql_test; // mysql> GRANT ALL PRIVILEGES ON modsql_test.* to USER@localhost; // // Note: substitute "USER" by your user name. // // To remove it: // // mysql> drop database modsql_test; func TaskTestMySQL(t *tasking.T) { // Format used in "github.com/serbaut/go-mysql" //db, err := sql.Open("mysql", fmt.Sprintf("mysql://%s@(unix)/%s?socket=%s", //username, dbname, host.mysql)) db, err := sql.Open("mysql", fmt.Sprintf("%s@unix(%s)/%s?parseTime=true", username, host.mysql, dbname)) if err != nil { t.Fatal(err) } if err = modsql.Load(db, filepath.Join("data", "sql", "mysql_init.sql")); err != nil { t.Error(err) } else { if err = modsql.Load(db, filepath.Join("data", "sql", "mysql_test.sql")); err != nil { t.Error(err) } testInsert(t, db, modsql.MySQL) if err = modsql.Load(db, filepath.Join("data", "sql", "mysql_drop.sql")); err != nil { t.Error(err) } } db.Close() if !t.Failed() { t.Log("--- PASS") } }
// NAME // test-sqlite - check data generated from ModSQL into a SQLite database func TaskTestSQLite(t *tasking.T) { filename := dbname + ".db" defer func() { if err := os.Remove(filename); err != nil { t.Error(err) } }() db, err := sql.Open("sqlite3", filename) if err != nil { t.Fatal(err) } if err = modsql.Load(db, filepath.Join("data", "sql", "sqlite_init.sql")); err != nil { t.Error(err) } else { if err = modsql.Load(db, filepath.Join("data", "sql", "sqlite_test.sql")); err != nil { t.Error(err) } testInsert(t, db, modsql.SQLite) if err = modsql.Load(db, filepath.Join("data", "sql", "sqlite_drop.sql")); err != nil { t.Error(err) } } db.Close() if !t.Failed() { t.Log("--- PASS") } }
// NAME // check data generated from ModSQL into a Postgre database // // DESCRIPTION // // To create the database: // // sudo -u postgres createuser USER --no-superuser --no-createrole --no-createdb // sudo -u postgres createdb modsql_test --owner USER // // Note: substitute "USER" by your user name. // // To remove it: // // sudo -u postgres dropdb modsql_test func TaskTestPostgres(t *tasking.T) { db, err := sql.Open("postgres", fmt.Sprintf("user=%s dbname=%s host=%s sslmode=disable", username, dbname, host.postgres)) if err != nil { t.Fatal(err) } if err = modsql.Load(db, filepath.Join("data", "sql", "postgres_init.sql")); err != nil { t.Error(err) } else { if err = modsql.Load(db, filepath.Join("data", "sql", "postgres_test.sql")); err != nil { t.Error(err) } testInsert(t, db, modsql.Postgres) if err = modsql.Load(db, filepath.Join("data", "sql", "postgres_drop.sql")); err != nil { t.Error(err) } } db.Close() if !t.Failed() { t.Log("--- PASS") } }
// NAME // package - cross compile gh and package it // // DESCRIPTION // Cross compile gh and package it into PWD/target func TaskPackage(t *tasking.T) { gopath, err := ioutil.TempDir("", "gh-build") os.Setenv("GOPATH", gopath) t.Logf("GOPATH=%s\n", gopath) path := fmt.Sprintf("%s%c%s", filepath.Join(gopath, "bin"), os.PathListSeparator, os.Getenv("PATH")) os.Setenv("PATH", path) t.Logf("PATH=%s\n", path) t.Logf("Packaging for %s...\n", runtime.GOOS) t.Log("Installing dependencies...") TaskInstallDeps(t) pwd, err := os.Getwd() if err != nil { t.Fatal(err) } ghPath := filepath.Join(gopath, "src", "github.com", "jingweno", "gh") t.Logf("Copying source from %s to %s\n", pwd, ghPath) err = copyDir(pwd, ghPath) if err != nil { t.Fatal(err) } err = os.Chdir(ghPath) if err != nil { t.Fatal(err) } t.Log("Cross-compiling...") godepPath := filepath.Join(ghPath, "Godeps", "_workspace") gopath = fmt.Sprintf("%s%c%s", gopath, os.PathListSeparator, godepPath) os.Setenv("GOPATH", gopath) TaskCrossCompile(t) source := filepath.Join(ghPath, "target") target := filepath.Join(pwd, "target") t.Logf("Copying build artifacts from %s to %s...\n", source, target) err = mkdirAll(target) if err != nil { t.Fatal(err) } err = copyBuildArtifacts(source, target) if err != nil { t.Fatal(err) } }
// Cross-compiles gh for current operating system. // // Cross-compiles gh for current operating system. The build artifacts will be in target/VERSION func TaskCrossCompile(t *tasking.T) { t.Log("Updating goxc...") err := t.Exec("go get -u github.com/laher/goxc") if err != nil { t.Errorf("Can't update goxc: %s\n", err) return } t.Logf("Cross-compiling gh for %s...\n", runtime.GOOS) err = t.Exec("goxc", "-wd=.", "-os="+runtime.GOOS, "-c="+runtime.GOOS) if err != nil { t.Errorf("Can't cross-compile gh: %s\n", err) return } }
// Cross-compiles gh for all supported platforms. // // Cross-compiles gh for all supported platforms. The build artifacts // will be in target/VERSION. This only works on darwin with Vagrant setup. func TaskCrossCompileAll(t *tasking.T) { t.Log("Removing build target...") err := os.RemoveAll("target") if err != nil { t.Errorf("Can't remove build target: %s\n", err) return } // for current t.Logf("Compiling for %s...\n", runtime.GOOS) TaskCrossCompile(t) if t.Failed() { return } // for linux t.Log("Compiling for linux...") err = t.Exec("vagrant ssh -c 'cd ~/src/github.com/jingweno/gh && git pull origin master && gotask cross-compile'") if err != nil { t.Errorf("Can't compile on linux: %s\n", err) return } }
// deployWindows is a routine for Windows func deployWindows(cfg *config, t *tasking.T) (err error) { logprefix := "deploy [windows]:" if verbose { t.Log(logprefix, "building executable") } name := filepath.Join(cfg.Path, cfg.PkgInfo.Name+".exe") cmd := exec.Command("go", "build", "-o", name, cfg.PkgInfo.ImportPath) if _, err = cmd.Output(); err != nil { return fmt.Errorf("go build: %v", err) } copyLib := func(lib string) (err error) { lib = strings.TrimPrefix(lib, "Qt") name := "Qt5" + lib + ".dll" orig := filepath.Join(cfg.QtInfo.BasePath, "bin", name) targ := filepath.Join(cfg.Path, name) err = copyFile(orig, targ) if err != nil { return } return } copyExtraLib := func(name string) (err error) { orig := filepath.Join(cfg.QtInfo.BasePath, "bin", name) targ := filepath.Join(cfg.Path, name) err = copyFile(orig, targ) if err != nil { return } return } if verbose { t.Log(logprefix, "copying libs") } for _, lib := range cfg.Profile.Libs["default"] { if err = copyLib(lib); err != nil { return } } for _, lib := range cfg.Profile.Libs["windows"] { if err = copyLib(lib); err != nil { return } } for _, lib := range cfg.Profile.Extra["windows"] { if err = copyExtraLib(lib); err != nil { return } } copyPlug := func(dir, name string) (err error) { name = "q" + name + ".dll" orig := filepath.Join(cfg.QtInfo.BasePath, "plugins", dir, name) targ := filepath.Join(cfg.Path, dir, name) if err = copyFile(orig, targ); err != nil { return } return } if verbose { t.Log(logprefix, "copying plugins") } err = os.Mkdir(filepath.Join(cfg.Path, "platforms"), 0755) if err != nil { return } for _, name := range cfg.Profile.Platforms["windows"] { if err = copyPlug("platforms", name); err != nil { return } } err = os.Mkdir(filepath.Join(cfg.Path, "imageformats"), 0755) if err != nil { return } for _, name := range cfg.Profile.Imageformats { if err = copyPlug("imageformats", name); err != nil { return } } copyMod := func(name string) (err error) { orig := filepath.Join(cfg.QtInfo.BasePath, name) targ := filepath.Join(cfg.Path, name) err = os.MkdirAll(filepath.Dir(targ), 0755) if err != nil { return } if err = copyTree(orig, targ); err != nil { return } return } if verbose { t.Log(logprefix, "copying modules") } err = copyTree(filepath.Join("project", "qml"), filepath.Join(cfg.Path, "qml")) if err != nil { return } for _, mods := range cfg.Profile.Modules { for _, name := range mods { targ := filepath.Join(name) if err = copyMod(targ); err != nil { return } } } return }
// deployLinux is a routine for Linux func deployLinux(cfg *config, t *tasking.T) (err error) { logprefix := "deploy [linux]:" if verbose { t.Log(logprefix, "building executable") } name := filepath.Join(cfg.Path, cfg.PkgInfo.Name) cmd := exec.Command("go", "build", "-o", name, cfg.PkgInfo.ImportPath) if _, err = cmd.Output(); err != nil { return fmt.Errorf("go build: %v", err) } err = ioutil.WriteFile(filepath.Join(cfg.Path, cfg.PkgInfo.Name+".sh"), []byte(shRun), 0755) if err != nil { return } copyLib := func(lib string) (err error) { lib = strings.TrimPrefix(lib, "Qt") name := "libQt5" + lib + ".so" orig := filepath.Join(cfg.QtInfo.LibPath, name+"."+cfg.QtInfo.Version) targ := filepath.Join(cfg.Path, name+".5") err = copyFile(orig, targ) if err != nil { return } return } copyExtraLib := func(name string) (err error) { orig := filepath.Join(cfg.QtInfo.LibPath, name) targ := filepath.Join(cfg.Path, name) err = copyFile(orig, targ) if err != nil { return } return } if verbose { t.Log(logprefix, "copying libs") } for _, lib := range cfg.Profile.Libs["default"] { if err = copyLib(lib); err != nil { return } } for _, lib := range cfg.Profile.Libs["linux"] { if err = copyLib(lib); err != nil { return } } for _, lib := range cfg.Profile.Extra["linux"] { if err = copyExtraLib(lib); err != nil { return } } copyPlug := func(dir, name string) (err error) { name = "libq" + name + ".so" orig := filepath.Join(cfg.QtInfo.BasePath, "plugins", dir, name) targ := filepath.Join(cfg.Path, dir, name) if err = copyFile(orig, targ); err != nil { return } return } if verbose { t.Log(logprefix, "copying plugins") } err = os.Mkdir(filepath.Join(cfg.Path, "platforms"), 0755) if err != nil { return } for _, name := range cfg.Profile.Platforms["linux"] { if err = copyPlug("platforms", name); err != nil { return } } err = os.Mkdir(filepath.Join(cfg.Path, "imageformats"), 0755) if err != nil { return } for _, name := range cfg.Profile.Imageformats { if err = copyPlug("imageformats", name); err != nil { return } } copyMod := func(name string) (err error) { orig := filepath.Join(cfg.QtInfo.BasePath, name) targ := filepath.Join(cfg.Path, name) err = os.MkdirAll(filepath.Dir(targ), 0755) if err != nil { return } if err = copyTree(orig, targ); err != nil { return } return } if verbose { t.Log(logprefix, "copying modules") } err = copyTree(filepath.Join("project", "qml"), filepath.Join(cfg.Path, "qml")) if err != nil { return } for category, mods := range cfg.Profile.Modules { dir := filepath.Join(strings.Split(category, "/")...) for _, name := range mods { targ := filepath.Join(dir, name) if err = copyMod(targ); err != nil { return } } } err = ioutil.WriteFile(filepath.Join(cfg.Path, "qt.conf"), []byte(qtConfLinux), 0666) if err != nil { return } return }
// deployDarwin is a routine for Darwin (OS X) func deployDarwin(cfg *config, t *tasking.T) (err error) { logprefix := "deploy [darwin]:" qlib := cfg.QtInfo.LibPath if verbose { t.Log(logprefix, "initial structure") } // target.app/Contents path := filepath.Join(cfg.Path, cfg.PkgInfo.Name+".app", "Contents") if err = os.MkdirAll(path, 0755); err != nil { return } // target.app/MacOS if err = os.Mkdir(filepath.Join(path, "MacOS"), 0755); err != nil { return } // target.app/Frameworks if err = os.Mkdir(filepath.Join(path, "Frameworks"), 0755); err != nil { return } // target.app/Plugins if err = os.Mkdir(filepath.Join(path, "Plugins"), 0755); err != nil { return } // target.app/Resources if err = os.Mkdir(filepath.Join(path, "Resources"), 0755); err != nil { return } // target.app/Info.plist if err = writeInfoPlist(path, cfg.PkgInfo); err != nil { return } // target.app/PkgInfo err = ioutil.WriteFile(filepath.Join(path, "PkgInfo"), []byte("APPL????\n"), 0666) if err != nil { return } // target.app/Resources/qt.conf err = ioutil.WriteFile(filepath.Join(path, "Resources", "qt.conf"), []byte(qtConfDarwin), 0666) if err != nil { return } // target.app/Resources/empty.lproj err = ioutil.WriteFile(filepath.Join(path, "Resources", "empty.lproj"), nil, 0666) if err != nil { return } if verbose { t.Log(logprefix, "building executable") } // target.app/MacOS/target name := filepath.Join(path, "MacOS", cfg.PkgInfo.Name) cmd := exec.Command("go", "build", "-o", name, cfg.PkgInfo.ImportPath) if _, err = cmd.Output(); err != nil { return fmt.Errorf("go build: %v", err) } if err = darwinRelink(qlib, name, true); err != nil { return } copyFw := func(fw string) (err error) { name := fw + ".framework" srcDir := filepath.Join(qlib, name, "Versions", "5") dstDir := filepath.Join(path, "Frameworks", name, "Versions", "5") err = os.MkdirAll(dstDir, 0755) if err != nil { return } err = copyFile(filepath.Join(srcDir, fw), filepath.Join(dstDir, fw)) if err != nil { return } err = darwinRelink(qlib, filepath.Join(dstDir, fw), false) return } if verbose { t.Log(logprefix, "copying frameworks") } // target.app/Frameworks for _, fw := range cfg.Profile.Libs["default"] { if err = copyFw(fw); err != nil { return } } for _, fw := range cfg.Profile.Libs["darwin"] { if err = copyFw(fw); err != nil { return } } copyPlug := func(dir, name string) (err error) { name = "libq" + name + ".dylib" orig := filepath.Join(cfg.QtInfo.BasePath, "plugins", dir, name) targ := filepath.Join(path, "Plugins", dir, name) if err = copyFile(orig, targ); err != nil { return } if err = darwinRelink(qlib, targ, false); err != nil { return } return } if verbose { t.Log(logprefix, "copying plugins") } // target.app/Plugins/platforms err = os.Mkdir(filepath.Join(path, "Plugins", "platforms"), 0755) if err != nil { return } for _, name := range cfg.Profile.Platforms["darwin"] { if err = copyPlug("platforms", name); err != nil { return } } // target.app/Plugins/imageformats err = os.Mkdir(filepath.Join(path, "Plugins", "imageformats"), 0755) if err != nil { return } for _, name := range cfg.Profile.Imageformats { if err = copyPlug("imageformats", name); err != nil { return } } copyMod := func(name string) (err error) { orig := filepath.Join(cfg.QtInfo.BasePath, name) targ := filepath.Join(path, "Resources", name) err = os.MkdirAll(filepath.Dir(targ), 0755) if err != nil { return } if err = copyTree(orig, targ); err != nil { return } // relink any *.dyld found in module filepath.Walk(targ, func(rpath string, info os.FileInfo, err error) error { if info.Mode().IsRegular() && filepath.Ext(rpath) == ".dylib" { if err = darwinRelink(qlib, rpath, false); err != nil { return err } } return nil }) return } if verbose { t.Log(logprefix, "copying modules") } // target.app/Resources/qml err = copyTree(filepath.Join("project", "qml"), filepath.Join(path, "Resources", "qml")) if err != nil { return } for category, mods := range cfg.Profile.Modules { dir := filepath.Join(strings.Split(category, "/")...) for _, name := range mods { targ := filepath.Join(dir, name) if err = copyMod(targ); err != nil { return } } } // disk image if t.Flags.Bool("dmg") { if verbose { t.Log(logprefix, "creating disk image") } err = os.Symlink("/Applications", filepath.Join(cfg.Path, "Applications")) if err != nil { return err } cmd := exec.Command("hdiutil", "create", "-srcfolder", cfg.Path, filepath.Join(cfg.Path, cfg.PkgInfo.Name+".dmg")) if err = cmd.Run(); err != nil { return err } } return }
// NAME // deploy - Run platform-specific deployment routine // // DESCRIPTION // Embeds resources, compiles binary, copies related libs and plugins, etc... // Distribution-ready application package will be the result of this task. // Supported platforms are: darwin, linux, windows. // // OPTIONS // --verbose, -v // Enable some logging // --dmg // Create an installable dmg (darwin only) func TaskDeploy(t *tasking.T) { deploy, ok := deployers[runtime.GOOS] if !ok { t.Fatal("deploy: platform unsupported:", runtime.GOOS) } verbose = t.Flags.Bool("verbose") // prepare output path path := fmt.Sprintf("%s/%s", outDir, runtime.GOOS) if err := os.RemoveAll(path); err != nil { t.Fatal(err) } if err := os.MkdirAll(path, 0755); err != nil { t.Fatal(err) } // gather info pkgInfo, err := getPkgInfo() if err != nil { t.Fatal(err) } qtInfo, err := getQtInfo() if err != nil { t.Fatal(err) } // read deploy profile buf, err := ioutil.ReadFile(deployProfileSrc) if err != nil { t.Fatal(err) } var profile deployProfile err = yaml.Unmarshal(buf, &profile) if err != nil { t.Fatalf("deploy: profile: %v\n", err) } else if verbose { t.Log("deploy: profile loaded") } cfg := config{ PkgInfo: pkgInfo, QtInfo: qtInfo, Path: path, Profile: profile, } if t.Flags.Bool("verbose") { t.Log("deploy: package name:", pkgInfo.Name) t.Logf("deploy: qt base: %s (%s)\n", qtInfo.BasePath, qtInfo.Version) } // embed resources if verbose { t.Log("deploy: embedding resources") } if err := exec.Command("rice", "embed-go").Run(); err != nil { t.Fatalf("deploy: rice: %v", err) } // run deployment if err := deploy(&cfg, t); err != nil { if err := os.RemoveAll(path); err != nil { t.Fatal(err) } t.Fatal(err) } // clean leftovers if err := exec.Command("rice", "clean").Run(); err != nil { t.Fatalf("clean: rice: %v", err) } }