44
bundle/bundle.go
Normal file
44
bundle/bundle.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package bundle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/metrue/fx/bundler"
|
||||
"github.com/metrue/fx/bundler/d"
|
||||
golang "github.com/metrue/fx/bundler/go"
|
||||
"github.com/metrue/fx/bundler/java"
|
||||
"github.com/metrue/fx/bundler/julia"
|
||||
"github.com/metrue/fx/bundler/node"
|
||||
"github.com/metrue/fx/bundler/perl"
|
||||
"github.com/metrue/fx/bundler/python"
|
||||
"github.com/metrue/fx/bundler/ruby"
|
||||
"github.com/metrue/fx/bundler/rust"
|
||||
)
|
||||
|
||||
// Bundle function to project
|
||||
func Bundle(workdir string, language string, fn string, deps ...string) error {
|
||||
var bundler bundler.Bundler
|
||||
switch language {
|
||||
case "d":
|
||||
bundler = d.New()
|
||||
case "node":
|
||||
bundler = node.New()
|
||||
case "go":
|
||||
bundler = golang.New()
|
||||
case "java":
|
||||
bundler = java.New()
|
||||
case "julia":
|
||||
bundler = julia.New()
|
||||
case "perl":
|
||||
bundler = perl.New()
|
||||
case "python":
|
||||
bundler = python.New()
|
||||
case "ruby":
|
||||
bundler = ruby.New()
|
||||
case "rust":
|
||||
bundler = rust.New()
|
||||
default:
|
||||
return fmt.Errorf("%s not suppported yet", language)
|
||||
}
|
||||
return bundler.Bundle(workdir, fn, deps...)
|
||||
}
|
||||
117
bundle/bundler_test.go
Normal file
117
bundle/bundler_test.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package bundle
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func createFn(content string, t *testing.T) string {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(fd.Name(), []byte(content), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return fd.Name()
|
||||
}
|
||||
|
||||
func TestBundle(t *testing.T) {
|
||||
workdir, err := ioutil.TempDir("", "fx-test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(workdir)
|
||||
|
||||
cases := []struct {
|
||||
workdir string
|
||||
language string
|
||||
fn string
|
||||
deps []string
|
||||
}{
|
||||
{
|
||||
workdir: workdir,
|
||||
language: "d",
|
||||
fn: `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
workdir: workdir,
|
||||
language: "go",
|
||||
fn: `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
workdir: workdir,
|
||||
language: "java",
|
||||
fn: `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
workdir: workdir,
|
||||
language: "julia",
|
||||
fn: `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
workdir: workdir,
|
||||
language: "perl",
|
||||
fn: `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
workdir: workdir,
|
||||
language: "python",
|
||||
fn: `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
workdir: workdir,
|
||||
language: "ruby",
|
||||
fn: `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}
|
||||
`,
|
||||
},
|
||||
{
|
||||
workdir: workdir,
|
||||
language: "rust",
|
||||
fn: `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}
|
||||
`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
fn := createFn(c.fn, t)
|
||||
defer os.Remove(fn)
|
||||
|
||||
if err := Bundle(c.workdir, c.language, fn, c.deps...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
100
bundler/bundler.go
Normal file
100
bundler/bundler.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package bundler
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gobuffalo/packd"
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
// Bundler defines interface
|
||||
type Bundler interface {
|
||||
Scaffold(output string) error
|
||||
Bundle(output string, fn string, deps ...string) error
|
||||
}
|
||||
|
||||
// IsHandler check if it's handle file
|
||||
func IsHandler(name string, lang string) bool {
|
||||
extLangMapping := map[string]string{
|
||||
".js": "node",
|
||||
".go": "go",
|
||||
".rb": "ruby",
|
||||
".py": "python",
|
||||
".php": "php",
|
||||
".jl": "julia",
|
||||
".java": "java",
|
||||
".d": "d",
|
||||
".rs": "rust",
|
||||
".pl": "perl",
|
||||
}
|
||||
|
||||
basename := filepath.Base(name)
|
||||
nameWithoutExt := strings.TrimSuffix(basename, filepath.Ext(basename))
|
||||
if extLangMapping[filepath.Ext(basename)] != lang {
|
||||
return false
|
||||
}
|
||||
|
||||
return (nameWithoutExt == "fx" ||
|
||||
// Fx is for Java
|
||||
nameWithoutExt == "Fx" ||
|
||||
// mod.rs is for Rust)
|
||||
nameWithoutExt == "mod")
|
||||
}
|
||||
|
||||
// Restore directory from packr box
|
||||
func Restore(box *packr.Box, output string) error {
|
||||
if err := box.Walk(func(name string, fd packd.File) error {
|
||||
content, err := box.Find(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dest := filepath.Join(output, name)
|
||||
if err := utils.EnsureFile(dest); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(dest, content, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Bundle bundle a function
|
||||
func Bundle(box *packr.Box, output string, language string, fn string, deps ...string) error {
|
||||
if err := Restore(box, output); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := utils.Merge(output, deps...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Replace the default handler source file with given function source file
|
||||
if err := filepath.Walk(output, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if IsHandler(path, language) {
|
||||
if err := utils.CopyFile(fn, path); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
51
bundler/bundler_test.go
Normal file
51
bundler/bundler_test.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package bundler
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
)
|
||||
|
||||
func TestBundler(t *testing.T) {
|
||||
t.Run("Restore", func(t *testing.T) {
|
||||
box := packr.New("", "./node/assets")
|
||||
outputDir, err := ioutil.TempDir("", "fx_koa")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
if err := Restore(box, outputDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Bundle", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content := `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}`
|
||||
if err = ioutil.WriteFile(fd.Name(), []byte(content), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_koa")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
box := packr.New("", "./node/assets")
|
||||
if err := Bundle(box, outputDir, "node", fd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
32
bundler/d/d.go
Normal file
32
bundler/d/d.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package d
|
||||
|
||||
import (
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
"github.com/metrue/fx/bundler"
|
||||
)
|
||||
|
||||
// D defines d bundler
|
||||
type D struct {
|
||||
assets *packr.Box
|
||||
}
|
||||
|
||||
// New a koa bundler
|
||||
func New() *D {
|
||||
return &D{
|
||||
assets: packr.New("", "./assets"),
|
||||
}
|
||||
}
|
||||
|
||||
// Scaffold a koa app
|
||||
func (d *D) Scaffold(output string) error {
|
||||
return bundler.Restore(d.assets, output)
|
||||
}
|
||||
|
||||
// Bundle a function into a koa project
|
||||
func (d *D) Bundle(output string, fn string, deps ...string) error {
|
||||
return bundler.Bundle(d.assets, output, "d", fn, deps...)
|
||||
}
|
||||
|
||||
var (
|
||||
_ bundler.Bundler = &D{}
|
||||
)
|
||||
32
bundler/go/go.go
Normal file
32
bundler/go/go.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package golang
|
||||
|
||||
import (
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
"github.com/metrue/fx/bundler"
|
||||
)
|
||||
|
||||
// Gin defines javascript bundler
|
||||
type Gin struct {
|
||||
assets *packr.Box
|
||||
}
|
||||
|
||||
// New a koa bundler
|
||||
func New() *Gin {
|
||||
return &Gin{
|
||||
assets: packr.New("", "./assets"),
|
||||
}
|
||||
}
|
||||
|
||||
// Scaffold a koa app
|
||||
func (g *Gin) Scaffold(output string) error {
|
||||
return bundler.Restore(g.assets, output)
|
||||
}
|
||||
|
||||
// Bundle a function into a koa project
|
||||
func (g *Gin) Bundle(output string, fn string, deps ...string) error {
|
||||
return bundler.Bundle(g.assets, output, "go", fn, deps...)
|
||||
}
|
||||
|
||||
var (
|
||||
_ bundler.Bundler = &Gin{}
|
||||
)
|
||||
143
bundler/go/go_test.go
Normal file
143
bundler/go/go_test.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package golang
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
func TestKoaBundler(t *testing.T) {
|
||||
t.Run("Scaffold", func(t *testing.T) {
|
||||
outputDir, err := ioutil.TempDir("", "fx_koa")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
koa := New()
|
||||
if err := koa.Scaffold(outputDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, _, _, err := utils.Diff(outputDir, "./assets")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff {
|
||||
t.Fatalf("%s is not equal with %s", outputDir, "./assets")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleSingleFunc", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content := `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}`
|
||||
err = ioutil.WriteFile(fd.Name(), []byte(content), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_koa")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
koa := New()
|
||||
if err := koa.Bundle(outputDir, fd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(content)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
|
||||
preHandleFunc, err := ioutil.ReadFile("./assets/fx.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(pre, preHandleFunc) {
|
||||
{
|
||||
}
|
||||
t.Fatalf("it should get %s but got %s", preHandleFunc, pre)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleFuncAndDeps", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content, err := ioutil.ReadFile("./assets/fx.go")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(fd.Name(), content, 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addFunc := `
|
||||
module.exports = (a, b) => a+b
|
||||
`
|
||||
addFd, err := ioutil.TempFile("", "fx_add_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_koa")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
koa := New()
|
||||
if err := koa.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(addFunc)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
if pre != nil {
|
||||
t.Fatal(pre)
|
||||
}
|
||||
})
|
||||
}
|
||||
32
bundler/java/java.go
Normal file
32
bundler/java/java.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package java
|
||||
|
||||
import (
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
"github.com/metrue/fx/bundler"
|
||||
)
|
||||
|
||||
// Java defines javascript bundler
|
||||
type Java struct {
|
||||
assets *packr.Box
|
||||
}
|
||||
|
||||
// New a koa bundler
|
||||
func New() *Java {
|
||||
return &Java{
|
||||
assets: packr.New("", "./assets"),
|
||||
}
|
||||
}
|
||||
|
||||
// Scaffold a koa app
|
||||
func (k *Java) Scaffold(output string) error {
|
||||
return bundler.Restore(k.assets, output)
|
||||
}
|
||||
|
||||
// Bundle a function into a koa project
|
||||
func (k *Java) Bundle(output string, fn string, deps ...string) error {
|
||||
return bundler.Bundle(k.assets, output, "java", fn, deps...)
|
||||
}
|
||||
|
||||
var (
|
||||
_ bundler.Bundler = &Java{}
|
||||
)
|
||||
155
bundler/java/java_test.go
Normal file
155
bundler/java/java_test.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package java
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
func TestJavaBundler(t *testing.T) {
|
||||
t.Run("Scaffold", func(t *testing.T) {
|
||||
outputDir, err := ioutil.TempDir("", "fx_java")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
java := New()
|
||||
if err := java.Scaffold(outputDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, _, _, err := utils.Diff(outputDir, "./assets")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff {
|
||||
t.Fatalf("%s is not equal with %s", outputDir, "./assets")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleSingleFunc", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.java")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content := `package fx;
|
||||
|
||||
import io.javalin.Javalin;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class app {
|
||||
public static void main(String[] args) {
|
||||
Javalin app = Javalin.start(3000);
|
||||
Fx handler = new Fx();
|
||||
app.post("/", ctx -> {
|
||||
JSONObject obj = new JSONObject(ctx.body());
|
||||
ctx.result(""+handler.handle(obj));
|
||||
});
|
||||
}
|
||||
}
|
||||
`
|
||||
err = ioutil.WriteFile(fd.Name(), []byte(content), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_java")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
java := New()
|
||||
if err := java.Bundle(outputDir, fd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(content)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
|
||||
preHandleFunc, err := ioutil.ReadFile("./assets/src/main/java/fx/Fx.java")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(pre, preHandleFunc) {
|
||||
{
|
||||
}
|
||||
t.Fatalf("it should get %s but got %s", preHandleFunc, pre)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleFuncAndDeps", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content, err := ioutil.ReadFile("./assets/src/main/java/fx/Fx.java")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(fd.Name(), content, 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addFunc := `
|
||||
module.exports = (a, b) => a+b
|
||||
`
|
||||
addFd, err := ioutil.TempFile("", "fx_add_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_java")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
java := New()
|
||||
if err := java.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(addFunc)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
if pre != nil {
|
||||
t.Fatal(pre)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
struct Input
|
||||
a::Number
|
||||
b::Number
|
||||
32
bundler/julia/julia.go
Normal file
32
bundler/julia/julia.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package julia
|
||||
|
||||
import (
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
"github.com/metrue/fx/bundler"
|
||||
)
|
||||
|
||||
// Julia defines javascript bundler
|
||||
type Julia struct {
|
||||
assets *packr.Box
|
||||
}
|
||||
|
||||
// New a koa bundler
|
||||
func New() *Julia {
|
||||
return &Julia{
|
||||
assets: packr.New("", "./assets"),
|
||||
}
|
||||
}
|
||||
|
||||
// Scaffold a koa app
|
||||
func (k *Julia) Scaffold(output string) error {
|
||||
return bundler.Restore(k.assets, output)
|
||||
}
|
||||
|
||||
// Bundle a function into a koa project
|
||||
func (k *Julia) Bundle(output string, fn string, deps ...string) error {
|
||||
return bundler.Bundle(k.assets, output, "julia", fn, deps...)
|
||||
}
|
||||
|
||||
var (
|
||||
_ bundler.Bundler = &Julia{}
|
||||
)
|
||||
148
bundler/julia/julia_test.go
Normal file
148
bundler/julia/julia_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package julia
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
func TestJuliaBundler(t *testing.T) {
|
||||
t.Run("Scaffold", func(t *testing.T) {
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Scaffold(outputDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, _, _, err := utils.Diff(outputDir, "./assets")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff {
|
||||
t.Fatalf("%s is not equal with %s", outputDir, "./assets")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleSingleFunc", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.julia")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content := `struct Input
|
||||
a::Number
|
||||
b::Number
|
||||
end
|
||||
|
||||
fx = function(input::Input)
|
||||
return input.a + input.b
|
||||
end
|
||||
`
|
||||
err = ioutil.WriteFile(fd.Name(), []byte(content), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Bundle(outputDir, fd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle function should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(content)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
|
||||
preHandleFunc, err := ioutil.ReadFile("./assets/fx.jl")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(pre, preHandleFunc) {
|
||||
{
|
||||
}
|
||||
t.Fatalf("it should get %s but got %s", preHandleFunc, pre)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleFuncAndDeps", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content, err := ioutil.ReadFile("./assets/fx.jl")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(fd.Name(), content, 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addFunc := `
|
||||
module.exports = (a, b) => a+b
|
||||
`
|
||||
addFd, err := ioutil.TempFile("", "fx_add_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(addFunc)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
if pre != nil {
|
||||
t.Fatal(pre)
|
||||
}
|
||||
})
|
||||
}
|
||||
34
bundler/node/node.go
Normal file
34
bundler/node/node.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
"github.com/metrue/fx/bundler"
|
||||
)
|
||||
|
||||
const language = "node"
|
||||
|
||||
// Node defines node bundler
|
||||
type Node struct {
|
||||
assets *packr.Box
|
||||
}
|
||||
|
||||
// New a koa bundler
|
||||
func New() *Node {
|
||||
return &Node{
|
||||
assets: packr.New("", "./assets"),
|
||||
}
|
||||
}
|
||||
|
||||
// Scaffold a koa app
|
||||
func (k *Node) Scaffold(output string) error {
|
||||
return bundler.Restore(k.assets, output)
|
||||
}
|
||||
|
||||
// Bundle a function into a koa project
|
||||
func (k *Node) Bundle(output string, fn string, deps ...string) error {
|
||||
return bundler.Bundle(k.assets, output, language, fn, deps...)
|
||||
}
|
||||
|
||||
var (
|
||||
_ bundler.Bundler = &Node{}
|
||||
)
|
||||
143
bundler/node/node_test.go
Normal file
143
bundler/node/node_test.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
func TestNodeBundler(t *testing.T) {
|
||||
t.Run("Scaffold", func(t *testing.T) {
|
||||
outputDir, err := ioutil.TempDir("", "fx_koa")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
koa := New()
|
||||
if err := koa.Scaffold(outputDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, _, _, err := utils.Diff(outputDir, "./assets")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff {
|
||||
t.Fatalf("%s is not equal with %s", outputDir, "./assets")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleSingleFunc", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content := `
|
||||
module.exports = (ctx) => {
|
||||
ctx.body = 'hello fx'
|
||||
}`
|
||||
err = ioutil.WriteFile(fd.Name(), []byte(content), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_koa")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
koa := New()
|
||||
if err := koa.Bundle(outputDir, fd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(content)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
|
||||
preHandleFunc, err := ioutil.ReadFile("./assets/fx.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(pre, preHandleFunc) {
|
||||
{
|
||||
}
|
||||
t.Fatalf("it should get %s but got %s", preHandleFunc, pre)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleFuncAndDeps", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content, err := ioutil.ReadFile("./assets/fx.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(fd.Name(), content, 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addFunc := `
|
||||
module.exports = (a, b) => a+b
|
||||
`
|
||||
addFd, err := ioutil.TempFile("", "fx_add_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_koa")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
koa := New()
|
||||
if err := koa.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(addFunc)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
if pre != nil {
|
||||
t.Fatal(pre)
|
||||
}
|
||||
})
|
||||
}
|
||||
32
bundler/perl/perl.go
Normal file
32
bundler/perl/perl.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package perl
|
||||
|
||||
import (
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
"github.com/metrue/fx/bundler"
|
||||
)
|
||||
|
||||
// Julia defines javascript bundler
|
||||
type Julia struct {
|
||||
assets *packr.Box
|
||||
}
|
||||
|
||||
// New a koa bundler
|
||||
func New() *Julia {
|
||||
return &Julia{
|
||||
assets: packr.New("", "./assets"),
|
||||
}
|
||||
}
|
||||
|
||||
// Scaffold a koa app
|
||||
func (k *Julia) Scaffold(output string) error {
|
||||
return bundler.Restore(k.assets, output)
|
||||
}
|
||||
|
||||
// Bundle a function into a koa project
|
||||
func (k *Julia) Bundle(output string, fn string, deps ...string) error {
|
||||
return bundler.Bundle(k.assets, output, "perl", fn, deps...)
|
||||
}
|
||||
|
||||
var (
|
||||
_ bundler.Bundler = &Julia{}
|
||||
)
|
||||
148
bundler/perl/perl_test.go
Normal file
148
bundler/perl/perl_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package perl
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
func TestJuliaBundler(t *testing.T) {
|
||||
t.Run("Scaffold", func(t *testing.T) {
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Scaffold(outputDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, _, _, err := utils.Diff(outputDir, "./assets")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff {
|
||||
t.Fatalf("%s is not equal with %s", outputDir, "./assets")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleSingleFunc", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.julia")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content := `struct Input
|
||||
a::Number
|
||||
b::Number
|
||||
end
|
||||
|
||||
fx = function(input::Input)
|
||||
return input.a + input.b
|
||||
end
|
||||
`
|
||||
err = ioutil.WriteFile(fd.Name(), []byte(content), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Bundle(outputDir, fd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle function should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(content)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
|
||||
preHandleFunc, err := ioutil.ReadFile("./assets/fx.pl")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(pre, preHandleFunc) {
|
||||
{
|
||||
}
|
||||
t.Fatalf("it should get %s but got %s", preHandleFunc, pre)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleFuncAndDeps", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content, err := ioutil.ReadFile("./assets/fx.pl")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(fd.Name(), content, 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addFunc := `
|
||||
module.exports = (a, b) => a+b
|
||||
`
|
||||
addFd, err := ioutil.TempFile("", "fx_add_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(addFunc)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
if pre != nil {
|
||||
t.Fatal(pre)
|
||||
}
|
||||
})
|
||||
}
|
||||
32
bundler/python/python.go
Normal file
32
bundler/python/python.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package python
|
||||
|
||||
import (
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
"github.com/metrue/fx/bundler"
|
||||
)
|
||||
|
||||
// Julia defines javascript bundler
|
||||
type Julia struct {
|
||||
assets *packr.Box
|
||||
}
|
||||
|
||||
// New a koa bundler
|
||||
func New() *Julia {
|
||||
return &Julia{
|
||||
assets: packr.New("", "./assets"),
|
||||
}
|
||||
}
|
||||
|
||||
// Scaffold a koa app
|
||||
func (k *Julia) Scaffold(output string) error {
|
||||
return bundler.Restore(k.assets, output)
|
||||
}
|
||||
|
||||
// Bundle a function into a koa project
|
||||
func (k *Julia) Bundle(output string, fn string, deps ...string) error {
|
||||
return bundler.Bundle(k.assets, output, "python", fn, deps...)
|
||||
}
|
||||
|
||||
var (
|
||||
_ bundler.Bundler = &Julia{}
|
||||
)
|
||||
148
bundler/python/python_test.go
Normal file
148
bundler/python/python_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package python
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
func TestJuliaBundler(t *testing.T) {
|
||||
t.Run("Scaffold", func(t *testing.T) {
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Scaffold(outputDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, _, _, err := utils.Diff(outputDir, "./assets")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff {
|
||||
t.Fatalf("%s is not equal with %s", outputDir, "./assets")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleSingleFunc", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.julia")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content := `struct Input
|
||||
a::Number
|
||||
b::Number
|
||||
end
|
||||
|
||||
fx = function(input::Input)
|
||||
return input.a + input.b
|
||||
end
|
||||
`
|
||||
err = ioutil.WriteFile(fd.Name(), []byte(content), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Bundle(outputDir, fd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle function should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(content)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
|
||||
preHandleFunc, err := ioutil.ReadFile("./assets/fx.py")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(pre, preHandleFunc) {
|
||||
{
|
||||
}
|
||||
t.Fatalf("it should get %s but got %s", preHandleFunc, pre)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleFuncAndDeps", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content, err := ioutil.ReadFile("./assets/fx.py")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(fd.Name(), content, 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addFunc := `
|
||||
module.exports = (a, b) => a+b
|
||||
`
|
||||
addFd, err := ioutil.TempFile("", "fx_add_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(addFunc)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
if pre != nil {
|
||||
t.Fatal(pre)
|
||||
}
|
||||
})
|
||||
}
|
||||
32
bundler/ruby/ruby.go
Normal file
32
bundler/ruby/ruby.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package ruby
|
||||
|
||||
import (
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
"github.com/metrue/fx/bundler"
|
||||
)
|
||||
|
||||
// Julia defines javascript bundler
|
||||
type Julia struct {
|
||||
assets *packr.Box
|
||||
}
|
||||
|
||||
// New a koa bundler
|
||||
func New() *Julia {
|
||||
return &Julia{
|
||||
assets: packr.New("", "./assets"),
|
||||
}
|
||||
}
|
||||
|
||||
// Scaffold a koa app
|
||||
func (k *Julia) Scaffold(output string) error {
|
||||
return bundler.Restore(k.assets, output)
|
||||
}
|
||||
|
||||
// Bundle a function into a koa project
|
||||
func (k *Julia) Bundle(output string, fn string, deps ...string) error {
|
||||
return bundler.Bundle(k.assets, output, "ruby", fn, deps...)
|
||||
}
|
||||
|
||||
var (
|
||||
_ bundler.Bundler = &Julia{}
|
||||
)
|
||||
148
bundler/ruby/ruby_test.go
Normal file
148
bundler/ruby/ruby_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package ruby
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
func TestJuliaBundler(t *testing.T) {
|
||||
t.Run("Scaffold", func(t *testing.T) {
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Scaffold(outputDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, _, _, err := utils.Diff(outputDir, "./assets")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff {
|
||||
t.Fatalf("%s is not equal with %s", outputDir, "./assets")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleSingleFunc", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.julia")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content := `struct Input
|
||||
a::Number
|
||||
b::Number
|
||||
end
|
||||
|
||||
fx = function(input::Input)
|
||||
return input.a + input.b
|
||||
end
|
||||
`
|
||||
err = ioutil.WriteFile(fd.Name(), []byte(content), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Bundle(outputDir, fd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle function should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(content)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
|
||||
preHandleFunc, err := ioutil.ReadFile("./assets/fx.rb")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(pre, preHandleFunc) {
|
||||
{
|
||||
}
|
||||
t.Fatalf("it should get %s but got %s", preHandleFunc, pre)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleFuncAndDeps", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content, err := ioutil.ReadFile("./assets/fx.rb")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(fd.Name(), content, 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addFunc := `
|
||||
module.exports = (a, b) => a+b
|
||||
`
|
||||
addFd, err := ioutil.TempFile("", "fx_add_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(addFunc)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
if pre != nil {
|
||||
t.Fatal(pre)
|
||||
}
|
||||
})
|
||||
}
|
||||
32
bundler/rust/rust.go
Normal file
32
bundler/rust/rust.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package rust
|
||||
|
||||
import (
|
||||
"github.com/gobuffalo/packr/v2"
|
||||
"github.com/metrue/fx/bundler"
|
||||
)
|
||||
|
||||
// Julia defines javascript bundler
|
||||
type Julia struct {
|
||||
assets *packr.Box
|
||||
}
|
||||
|
||||
// New a koa bundler
|
||||
func New() *Julia {
|
||||
return &Julia{
|
||||
assets: packr.New("", "./assets"),
|
||||
}
|
||||
}
|
||||
|
||||
// Scaffold a koa app
|
||||
func (k *Julia) Scaffold(output string) error {
|
||||
return bundler.Restore(k.assets, output)
|
||||
}
|
||||
|
||||
// Bundle a function into a koa project
|
||||
func (k *Julia) Bundle(output string, fn string, deps ...string) error {
|
||||
return bundler.Bundle(k.assets, output, "rust", fn, deps...)
|
||||
}
|
||||
|
||||
var (
|
||||
_ bundler.Bundler = &Julia{}
|
||||
)
|
||||
148
bundler/rust/rust_test.go
Normal file
148
bundler/rust/rust_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package rust
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
func TestJuliaBundler(t *testing.T) {
|
||||
t.Run("Scaffold", func(t *testing.T) {
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Scaffold(outputDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, _, _, err := utils.Diff(outputDir, "./assets")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff {
|
||||
t.Fatalf("%s is not equal with %s", outputDir, "./assets")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleSingleFunc", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.julia")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content := `struct Input
|
||||
a::Number
|
||||
b::Number
|
||||
end
|
||||
|
||||
fx = function(input::Input)
|
||||
return input.a + input.b
|
||||
end
|
||||
`
|
||||
err = ioutil.WriteFile(fd.Name(), []byte(content), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Bundle(outputDir, fd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle function should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(content)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
|
||||
preHandleFunc, err := ioutil.ReadFile("./assets/src/fns/mod.rs")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(pre, preHandleFunc) {
|
||||
{
|
||||
}
|
||||
t.Fatalf("it should get %s but got %s", preHandleFunc, pre)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("BundleFuncAndDeps", func(t *testing.T) {
|
||||
fd, err := ioutil.TempFile("", "fx_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(fd.Name())
|
||||
|
||||
content, err := ioutil.ReadFile("./assets/src/fns/mod.rs")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(fd.Name(), content, 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
addFunc := `
|
||||
module.exports = (a, b) => a+b
|
||||
`
|
||||
addFd, err := ioutil.TempFile("", "fx_add_func_*.js")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(addFd.Name(), []byte(addFunc), 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
outputDir, err := ioutil.TempDir("", "fx_julia")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(outputDir)
|
||||
|
||||
julia := New()
|
||||
if err := julia.Bundle(outputDir, fd.Name(), addFd.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
diff, pre, cur, err := utils.Diff("./assets", outputDir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !diff {
|
||||
t.Fatalf("handle functino should be changed")
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cur, []byte(addFunc)) {
|
||||
t.Fatalf("it should be %s but got %s", content, cur)
|
||||
}
|
||||
if pre != nil {
|
||||
t.Fatal(pre)
|
||||
}
|
||||
})
|
||||
}
|
||||
3
fx.go
3
fx.go
@@ -159,6 +159,7 @@ func main() {
|
||||
middlewares.LoadConfig,
|
||||
middlewares.Provision,
|
||||
middlewares.Parse("up"),
|
||||
middlewares.Language(),
|
||||
middlewares.Binding,
|
||||
middlewares.Build,
|
||||
handlers.Up,
|
||||
@@ -221,6 +222,7 @@ func main() {
|
||||
middlewares.LoadConfig,
|
||||
middlewares.Provision,
|
||||
middlewares.Parse("image_build"),
|
||||
middlewares.Language(),
|
||||
handlers.BuildImage,
|
||||
),
|
||||
},
|
||||
@@ -237,6 +239,7 @@ func main() {
|
||||
middlewares.LoadConfig,
|
||||
middlewares.Provision,
|
||||
middlewares.Parse("image_export"),
|
||||
middlewares.Language(),
|
||||
handlers.ExportImage,
|
||||
),
|
||||
},
|
||||
|
||||
3
go.mod
3
go.mod
@@ -14,7 +14,8 @@ require (
|
||||
github.com/dsnet/compress v0.0.1 // indirect
|
||||
github.com/gin-gonic/gin v1.4.0
|
||||
github.com/gobuffalo/envy v1.8.1 // indirect
|
||||
github.com/gobuffalo/packr v1.30.1
|
||||
github.com/gobuffalo/packd v0.3.0
|
||||
github.com/gobuffalo/packr/v2 v2.5.1
|
||||
github.com/golang/mock v1.4.1
|
||||
github.com/golang/snappy v0.0.1 // indirect
|
||||
github.com/google/go-querystring v1.0.0
|
||||
|
||||
12
go.sum
12
go.sum
@@ -21,8 +21,6 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/apex/log v1.1.1 h1:BwhRZ0qbjYtTob0I+2M+smavV0kOC8XgcnGZcyL9liA=
|
||||
github.com/apex/log v1.1.1/go.mod h1:Ls949n1HFtXfbDcjiTTFQqkVUrte0puoIBfO3SVgwOA=
|
||||
github.com/apex/log v1.1.2 h1:bnDuVoi+o98wOdVqfEzNDlY0tcmBia7r4YkjS9EqGYk=
|
||||
github.com/apex/log v1.1.2/go.mod h1:SyfRweFO+TlkIJ3DVizTSeI1xk7jOIIqOnUPZQTTsww=
|
||||
github.com/apex/logs v0.0.3/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
|
||||
@@ -33,8 +31,6 @@ github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN
|
||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/briandowns/spinner v1.7.0 h1:aan1hBBOoscry2TXAkgtxkJiq7Se0+9pt+TUWaPrB4g=
|
||||
github.com/briandowns/spinner v1.7.0/go.mod h1://Zf9tMcxfRUA36V23M6YGEAv+kECGfvpnLTnb8n4XQ=
|
||||
github.com/briandowns/spinner v1.9.0 h1:+OMAisemaHar1hjuJ3Z2hIvNhQl9Y7GLPWUwwz2Pxo8=
|
||||
github.com/briandowns/spinner v1.9.0/go.mod h1://Zf9tMcxfRUA36V23M6YGEAv+kECGfvpnLTnb8n4XQ=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
@@ -99,8 +95,6 @@ github.com/gobuffalo/logger v1.0.0 h1:xw9Ko9EcC5iAFprrjJ6oZco9UpzS5MQ4jAwghsLHdy
|
||||
github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
|
||||
github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4=
|
||||
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
|
||||
github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg=
|
||||
github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIaviy289eRuk=
|
||||
github.com/gobuffalo/packr/v2 v2.5.1 h1:TFOeY2VoGamPjQLiNDT3mn//ytzk236VMO2j7iHxJR4=
|
||||
github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@@ -115,8 +109,6 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0 h1:Rd1kQnQu0Hq3qvJppYSG0HtP+f5LPPUiDswTLiEegLg=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1 h1:ocYkMQY5RrXTYgXl7ICpV0IXwlEQGwKIsery4gyXa1U=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -262,8 +254,6 @@ github.com/pierrec/lz4 v0.0.0-20190222153722-062282ea0dcf/go.mod h1:3/3N9NVKO0je
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.0 h1:J8lpUdobwIeCI7OiSxHqEwJUKvJwicL5+3v1oe2Yb4k=
|
||||
github.com/pkg/errors v0.9.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
@@ -323,8 +313,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk=
|
||||
github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
|
||||
github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E=
|
||||
github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
||||
@@ -6,14 +6,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/metrue/fx/bundle"
|
||||
"github.com/metrue/fx/constants"
|
||||
containerruntimes "github.com/metrue/fx/container_runtimes"
|
||||
"github.com/metrue/fx/context"
|
||||
"github.com/metrue/fx/hook"
|
||||
"github.com/metrue/fx/packer"
|
||||
"github.com/metrue/fx/pkg/spinner"
|
||||
"github.com/metrue/fx/utils"
|
||||
"github.com/otiai10/copy"
|
||||
)
|
||||
|
||||
// BuildImage build image
|
||||
@@ -26,23 +24,16 @@ func BuildImage(ctx context.Contexter) (err error) {
|
||||
defer os.RemoveAll(workdir)
|
||||
|
||||
sources := ctx.Get("sources").([]string)
|
||||
language := ctx.Get("language").(string)
|
||||
|
||||
if len(sources) == 0 {
|
||||
return fmt.Errorf("source file/directory of function required")
|
||||
}
|
||||
if len(sources) == 1 &&
|
||||
utils.IsDir(sources[0]) &&
|
||||
utils.HasDockerfile(sources[0]) {
|
||||
if err := copy.Copy(sources[0], workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := packer.Pack(workdir, sources...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hook.RunBeforeBuildHook(workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bundle.Bundle(workdir, language, sources[0], sources[1:]...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hook.RunBeforeBuildHook(workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
docker := ctx.Get("docker").(containerruntimes.ContainerRuntime)
|
||||
@@ -58,23 +49,16 @@ func BuildImage(ctx context.Contexter) (err error) {
|
||||
func ExportImage(ctx context.Contexter) (err error) {
|
||||
outputDir := ctx.Get("output").(string)
|
||||
sources := ctx.Get("sources").([]string)
|
||||
language := ctx.Get("language").(string)
|
||||
|
||||
if len(sources) == 0 {
|
||||
return fmt.Errorf("source file/directory of function required")
|
||||
}
|
||||
if len(sources) == 1 &&
|
||||
utils.IsDir(sources[0]) &&
|
||||
utils.HasDockerfile(sources[0]) {
|
||||
if err := copy.Copy(sources[0], outputDir); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := packer.Pack(outputDir, sources...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hook.RunBeforeBuildHook(outputDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bundle.Bundle(outputDir, language, sources[0], sources[1:]...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hook.RunBeforeBuildHook(outputDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("exported to %v: %v", outputDir, constants.CheckedSymbol)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/metrue/fx/bundle"
|
||||
containerruntimes "github.com/metrue/fx/container_runtimes"
|
||||
"github.com/metrue/fx/context"
|
||||
"github.com/metrue/fx/hook"
|
||||
@@ -12,7 +13,6 @@ import (
|
||||
"github.com/metrue/fx/pkg/spinner"
|
||||
"github.com/metrue/fx/types"
|
||||
"github.com/metrue/fx/utils"
|
||||
"github.com/otiai10/copy"
|
||||
)
|
||||
|
||||
// Build image
|
||||
@@ -40,26 +40,19 @@ func Build(ctx context.Contexter) (err error) {
|
||||
|
||||
// When only one directory given and there is a Dockerfile in given directory, treat it as a containerized project and skip packing
|
||||
sources := ctx.Get("sources").([]string)
|
||||
language := ctx.Get("language").(string)
|
||||
|
||||
if len(sources) == 0 {
|
||||
return fmt.Errorf("source file/directory of function required")
|
||||
}
|
||||
|
||||
if len(sources) == 1 &&
|
||||
utils.IsDir(sources[0]) &&
|
||||
utils.HasDockerfile(sources[0]) {
|
||||
if err := copy.Copy(sources[0], workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := packer.Pack(workdir, sources...); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := hook.RunBeforeBuildHook(workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := bundle.Bundle(workdir, language, sources[0], sources[1:]...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := hook.RunBeforeBuildHook(workdir); err != nil {
|
||||
return err
|
||||
}
|
||||
cloudType := ctx.Get("cloud_type").(string)
|
||||
name := ctx.Get("name").(string)
|
||||
if cloudType == types.CloudTypeK8S {
|
||||
|
||||
73
middlewares/language.go
Normal file
73
middlewares/language.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/metrue/fx/context"
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
// ExtLangMapping file extension mapping with programming language
|
||||
var ExtLangMapping = map[string]string{
|
||||
".js": "node",
|
||||
".go": "go",
|
||||
".rb": "ruby",
|
||||
".py": "python",
|
||||
".php": "php",
|
||||
".jl": "julia",
|
||||
".java": "java",
|
||||
".d": "d",
|
||||
".rs": "rust",
|
||||
".pl": "perl",
|
||||
}
|
||||
|
||||
func langFromFileName(fileName string) (string, error) {
|
||||
if fileName == "" {
|
||||
return "", fmt.Errorf("file name should not be empty")
|
||||
}
|
||||
|
||||
ext := filepath.Ext(fileName)
|
||||
lang, ok := ExtLangMapping[ext]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("could not find corresponse programming language for file extension %s", ext)
|
||||
}
|
||||
return lang, nil
|
||||
}
|
||||
|
||||
// Language to find out what language of function is
|
||||
func Language() func(ctx context.Contexter) (err error) {
|
||||
return func(ctx context.Contexter) error {
|
||||
sources := ctx.Get("sources").([]string)
|
||||
var language string
|
||||
for _, f := range sources {
|
||||
if utils.IsRegularFile(f) {
|
||||
lang, err := langFromFileName(f)
|
||||
if err == nil {
|
||||
language = lang
|
||||
}
|
||||
} else if utils.IsDir(f) {
|
||||
if err := filepath.Walk(f, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if utils.IsRegularFile(path) {
|
||||
lang, err := langFromFileName(path)
|
||||
if err == nil {
|
||||
language = lang
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if language == "" {
|
||||
return fmt.Errorf("could not tell programing language of your source codes")
|
||||
}
|
||||
ctx.Set("language", language)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
5
packer/images/php/Dockerfile
vendored
5
packer/images/php/Dockerfile
vendored
@@ -1,5 +0,0 @@
|
||||
FROM php:latest
|
||||
|
||||
COPY . .
|
||||
EXPOSE 3000
|
||||
CMD php -S 0.0.0.0:3000
|
||||
4
packer/images/php/fx.php
vendored
4
packer/images/php/fx.php
vendored
@@ -1,4 +0,0 @@
|
||||
<?php
|
||||
function Fx($input) {
|
||||
return $input["a"]+$input["b"];
|
||||
}
|
||||
6
packer/images/php/index.php
vendored
6
packer/images/php/index.php
vendored
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
include("fx.php");
|
||||
$data = file_get_contents("php://input");
|
||||
$res = json_decode($data,true);
|
||||
$v = Fx($res);
|
||||
echo $v;
|
||||
162
packer/packer.go
162
packer/packer.go
@@ -3,176 +3,14 @@ package packer
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gobuffalo/packr"
|
||||
"github.com/metrue/fx/utils"
|
||||
"github.com/otiai10/copy"
|
||||
)
|
||||
|
||||
var presets packr.Box
|
||||
|
||||
func init() {
|
||||
presets = packr.NewBox("./images")
|
||||
}
|
||||
|
||||
// Pack pack a file or directory into a Docker project
|
||||
func Pack(output string, input ...string) error {
|
||||
if len(input) == 0 {
|
||||
return fmt.Errorf("source file or directory required")
|
||||
}
|
||||
|
||||
var language string
|
||||
for _, f := range input {
|
||||
if utils.IsRegularFile(f) {
|
||||
lang, err := langFromFileName(f)
|
||||
if err == nil {
|
||||
language = lang
|
||||
}
|
||||
} else if utils.IsDir(f) {
|
||||
if err := filepath.Walk(f, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if utils.IsRegularFile(path) {
|
||||
lang, err := langFromFileName(path)
|
||||
if err == nil {
|
||||
language = lang
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if language == "" {
|
||||
return fmt.Errorf("could not tell programe language of your input source codes")
|
||||
}
|
||||
|
||||
if err := restore(output, language); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(input) == 1 {
|
||||
stat, err := os.Stat(input[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stat.Mode().IsRegular() {
|
||||
if err := filepath.Walk(output, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isHandler(path, language) {
|
||||
if err := copy.Copy(input[0], path); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if !hasFxHandleFile(language, input...) {
|
||||
msg := `it requires a fx handle file when input is not a single file function, e.g.
|
||||
fx.go for Golang
|
||||
Fx.java for Java
|
||||
fx.php for PHP
|
||||
fx.py for Python
|
||||
fx.js for JavaScript or Node
|
||||
fx.rb for Ruby
|
||||
fx.jl for Julia
|
||||
fx.pl for Perl
|
||||
fx.d for D`
|
||||
return fmt.Errorf(msg)
|
||||
}
|
||||
|
||||
if err := merge(output, input...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func restore(output string, lang string) error {
|
||||
for _, name := range presets.List() {
|
||||
prefix := fmt.Sprintf("%s/", lang)
|
||||
if strings.HasPrefix(name, prefix) {
|
||||
content, err := presets.FindString(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filePath := filepath.Join(output, strings.Replace(name, prefix, "", 1))
|
||||
if err := utils.EnsureFile(filePath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(filePath, []byte(content), 0666); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func merge(dest string, input ...string) error {
|
||||
for _, file := range input {
|
||||
stat, err := os.Stat(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stat.Mode().IsRegular() {
|
||||
targetFilePath := filepath.Join(dest, stat.Name())
|
||||
if err := utils.EnsureFile(targetFilePath); err != nil {
|
||||
return err
|
||||
}
|
||||
body, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(targetFilePath, body, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if stat.Mode().IsDir() {
|
||||
if err := filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stat.Mode().IsRegular() {
|
||||
destDir := filepath.Join(dest, filepath.Dir(path))
|
||||
if err := utils.EnsureDir(destDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := copy.Copy(file, destDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PackIntoK8SConfigMapFile pack function a K8S config map file
|
||||
func PackIntoK8SConfigMapFile(dir string) (string, error) {
|
||||
tree := map[string]string{}
|
||||
|
||||
@@ -1,182 +1,12 @@
|
||||
package packer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
func TestPacker(t *testing.T) {
|
||||
t.Run("Pack directory with Dockerfile in it", func(t *testing.T) {
|
||||
input := "./fixture/p1"
|
||||
output := "output-1"
|
||||
defer func() {
|
||||
os.RemoveAll(output)
|
||||
}()
|
||||
if err := Pack(output, input); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Pack directory only fx.js in it", func(t *testing.T) {
|
||||
input := "./fixture/p2"
|
||||
output := "output-2"
|
||||
defer func() {
|
||||
os.RemoveAll(output)
|
||||
}()
|
||||
if err := Pack(output, input); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Pack directory with fx.js and helper in it", func(t *testing.T) {
|
||||
input := "./fixture/p3"
|
||||
output := "output-3"
|
||||
defer func() {
|
||||
os.RemoveAll(output)
|
||||
}()
|
||||
if err := Pack(output, input); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Pack files list with fx.js in it", func(t *testing.T) {
|
||||
handleFile := "./fixture/p3/fx.js"
|
||||
helperFile := "./fixture/p3/helper.js"
|
||||
output := "output-4"
|
||||
defer func() {
|
||||
os.RemoveAll(output)
|
||||
}()
|
||||
if err := Pack(output, handleFile, helperFile); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Pack files list without fx.js in it", func(t *testing.T) {
|
||||
f1 := "./fixture/p3/helper.js"
|
||||
f2 := "./fixture/p3/helper.js"
|
||||
output := "output-5"
|
||||
defer func() {
|
||||
os.RemoveAll(output)
|
||||
}()
|
||||
if err := Pack(output, f1, f2); err == nil {
|
||||
t.Fatalf("should report error when there is not Dockerfile or fx.[ext] in it")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestTreeAndUnTree(t *testing.T) {
|
||||
_, err := PackIntoK8SConfigMapFile("./fixture/p1")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
langs := []string{
|
||||
"d",
|
||||
"go",
|
||||
"java",
|
||||
"julia",
|
||||
"node",
|
||||
"php",
|
||||
"python",
|
||||
"ruby",
|
||||
"rust",
|
||||
}
|
||||
for _, lang := range langs {
|
||||
output := fmt.Sprintf("output-%s-%d", lang, time.Now().Unix())
|
||||
defer func() {
|
||||
os.RemoveAll(output)
|
||||
}()
|
||||
if err := restore(output, lang); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
diffCmd := exec.Command("diff", "-r", output, "./images/"+lang)
|
||||
if stdoutStderr, err := diffCmd.CombinedOutput(); err != nil {
|
||||
fmt.Printf("%s\n", stdoutStderr)
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
// TODO should check the merge result
|
||||
t.Run("NoInput", func(t *testing.T) {
|
||||
dest := "./dest"
|
||||
_ = utils.EnsureDir("./dest")
|
||||
defer func() {
|
||||
os.RemoveAll(dest)
|
||||
}()
|
||||
|
||||
if err := merge(dest); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Files", func(t *testing.T) {
|
||||
dest := "./dest"
|
||||
_ = utils.EnsureDir("./dest")
|
||||
defer func() {
|
||||
os.RemoveAll(dest)
|
||||
}()
|
||||
|
||||
f1, err := ioutil.TempFile("", "fx.*.txt")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.Remove(f1.Name())
|
||||
|
||||
f2, err := ioutil.TempFile("", "fx.*.txt")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.Remove(f2.Name())
|
||||
|
||||
if err := merge(dest, f1.Name(), f2.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Directories", func(t *testing.T) {
|
||||
dest := "./dest"
|
||||
_ = utils.EnsureDir("./dest")
|
||||
defer func() {
|
||||
os.RemoveAll(dest)
|
||||
}()
|
||||
|
||||
if err := merge(dest, "./fixture/p1"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Files and Directories", func(t *testing.T) {
|
||||
dest := "./dest"
|
||||
_ = utils.EnsureDir("./dest")
|
||||
defer func() {
|
||||
os.RemoveAll(dest)
|
||||
}()
|
||||
|
||||
f1, err := ioutil.TempFile("", "fx.*.txt")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.Remove(f1.Name())
|
||||
|
||||
f2, err := ioutil.TempFile("", "fx.*.txt")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer os.Remove(f2.Name())
|
||||
|
||||
if err := merge(dest, "./fixture/p1", f1.Name(), f2.Name()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,11 +2,7 @@ package packer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/metrue/fx/utils"
|
||||
)
|
||||
|
||||
// ExtLangMapping file extension mapping with programming language
|
||||
@@ -23,20 +19,6 @@ var ExtLangMapping = map[string]string{
|
||||
".pl": "perl",
|
||||
}
|
||||
|
||||
func isHandler(name string, lang string) bool {
|
||||
basename := filepath.Base(name)
|
||||
nameWithoutExt := strings.TrimSuffix(basename, filepath.Ext(basename))
|
||||
if ExtLangMapping[filepath.Ext(basename)] != lang {
|
||||
return false
|
||||
}
|
||||
|
||||
return (nameWithoutExt == "fx" ||
|
||||
// Fx is for Java
|
||||
nameWithoutExt == "Fx" ||
|
||||
// mod.rs is for Rust)
|
||||
nameWithoutExt == "mod")
|
||||
}
|
||||
|
||||
func langFromFileName(fileName string) (string, error) {
|
||||
if fileName == "" {
|
||||
return "", fmt.Errorf("file name should not be empty")
|
||||
@@ -49,28 +31,3 @@ func langFromFileName(fileName string) (string, error) {
|
||||
}
|
||||
return lang, nil
|
||||
}
|
||||
|
||||
func hasFxHandleFile(lang string, input ...string) bool {
|
||||
var handleFile string
|
||||
for _, file := range input {
|
||||
if utils.IsRegularFile(file) && isHandler(file, lang) {
|
||||
handleFile = file
|
||||
break
|
||||
} else if utils.IsDir(file) {
|
||||
if err := filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if utils.IsRegularFile(path) && isHandler(info.Name(), lang) {
|
||||
handleFile = path
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return handleFile != ""
|
||||
}
|
||||
|
||||
125
utils/dir.go
Normal file
125
utils/dir.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/otiai10/copy"
|
||||
)
|
||||
|
||||
// Merge inputs into dest
|
||||
func Merge(dest string, input ...string) error {
|
||||
for _, file := range input {
|
||||
stat, err := os.Stat(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stat.Mode().IsRegular() {
|
||||
targetFilePath := filepath.Join(dest, stat.Name())
|
||||
if err := EnsureFile(targetFilePath); err != nil {
|
||||
return err
|
||||
}
|
||||
body, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(targetFilePath, body, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if stat.Mode().IsDir() {
|
||||
if err := filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if stat.Mode().IsRegular() {
|
||||
destDir := filepath.Join(dest, filepath.Dir(path))
|
||||
if err := EnsureDir(destDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := copy.Copy(file, destDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Diff two directory
|
||||
func Diff(src string, dst string) (diff bool, pre []byte, cur []byte, err error) {
|
||||
src, err = filepath.Abs(src)
|
||||
if err != nil {
|
||||
return true, nil, nil, err
|
||||
}
|
||||
|
||||
dst, err = filepath.Abs(dst)
|
||||
if err != nil {
|
||||
return true, nil, nil, err
|
||||
}
|
||||
|
||||
srcMap := map[string][]byte{}
|
||||
if err := filepath.Walk(src, func(path string, info os.FileInfo, e error) error {
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
if IsDir(path) {
|
||||
return nil
|
||||
}
|
||||
content, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p := strings.Replace(path, src, "", -1)
|
||||
srcMap[p] = content
|
||||
return nil
|
||||
}); err != nil {
|
||||
return true, nil, nil, err
|
||||
}
|
||||
|
||||
dstMap := map[string][]byte{}
|
||||
if err := filepath.Walk(dst, func(path string, info os.FileInfo, e error) error {
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
if IsDir(path) {
|
||||
return nil
|
||||
}
|
||||
content, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p := strings.Replace(path, dst, "", -1)
|
||||
dstMap[p] = content
|
||||
return nil
|
||||
}); err != nil {
|
||||
return true, nil, nil, err
|
||||
}
|
||||
|
||||
for k, v := range srcMap {
|
||||
if !reflect.DeepEqual(dstMap[k], v) {
|
||||
return true, v, dstMap[k], nil
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range dstMap {
|
||||
if !reflect.DeepEqual(srcMap[k], v) {
|
||||
return true, srcMap[k], v, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil, nil, nil
|
||||
}
|
||||
Reference in New Issue
Block a user