github.com/aminjam/goflat@v0.4.1-0.20160331105230-ec639fc0d5b3/goflatbuilder.go (about) 1 package goflat 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "math/rand" 8 "os" 9 "path/filepath" 10 "strings" 11 "text/template" 12 ) 13 14 //Builder pattern seems to be the most appropriate structure for building a `Flat` struct 15 type FlatBuilder interface { 16 EvalGoInputs(files []string) error 17 EvalGoPipes(file string) error 18 EvalMainGo() error 19 Flat() *Flat 20 } 21 22 type flatBuilder struct { 23 flat *Flat 24 baseDir string 25 } 26 27 func (builder *flatBuilder) cp(file string) (string, error) { 28 outFile := filepath.Join(builder.baseDir, nameGenerator()) 29 in, err := os.Open(file) 30 if err != nil { 31 return "", err 32 } 33 defer in.Close() 34 out, err := os.Create(outFile) 35 if err != nil { 36 return "", err 37 } 38 defer out.Close() 39 _, err = io.Copy(out, in) 40 cerr := out.Close() 41 if err != nil { 42 return "", err 43 } 44 return outFile, cerr 45 } 46 47 func (builder *flatBuilder) EvalGoInputs(files []string) error { 48 builder.flat.GoInputs = make([]goInput, len(files)) 49 for k, v := range files { 50 gi := newGoInput(v) 51 file, err := builder.cp(gi.Path) 52 if err != nil { 53 return fmt.Errorf("%s:%s", ErrMissingOnDisk, err.Error()) 54 } 55 gi.Path = file 56 builder.flat.GoInputs[k] = gi 57 } 58 return nil 59 } 60 61 func (builder *flatBuilder) EvalGoPipes(file string) error { 62 defaultPipes, err := builder.defaultPipes() 63 if err != nil { 64 return err 65 } 66 builder.flat.DefaultPipes = defaultPipes 67 68 if file != "" { 69 customPipes, err := builder.cp(file) 70 if err != nil { 71 return fmt.Errorf("%s:%s", ErrMissingOnDisk, err.Error()) 72 } 73 builder.flat.CustomPipes = customPipes 74 } 75 return nil 76 } 77 78 func (builder *flatBuilder) EvalMainGo() error { 79 outFile := filepath.Join(builder.baseDir, nameGenerator()) 80 main, err := os.Create(outFile) 81 if err != nil { 82 return err 83 } 84 defer main.Close() 85 86 var tmpl = template.Must(template.New("main").Parse(MainGotempl)) 87 if err := tmpl.Execute(main, builder.flat); err != nil { 88 return err 89 } 90 builder.flat.MainGo = outFile 91 return nil 92 } 93 94 func (builder *flatBuilder) Flat() *Flat { 95 return builder.flat 96 } 97 98 //NewFlatBuilder initializes a new instance of `FlatBuilder` interface 99 func NewFlatBuilder(baseDir, template string) (FlatBuilder, error) { 100 if _, err := os.Stat(baseDir); err != nil { 101 return nil, fmt.Errorf("%s:%s", ErrMissingOnDisk, err.Error()) 102 } 103 if _, err := os.Stat(template); err != nil { 104 return nil, fmt.Errorf("%s:%s", ErrMissingOnDisk, err.Error()) 105 } 106 107 src_dir := filepath.Join(baseDir, "src") 108 os.MkdirAll(src_dir, 0777) 109 110 goflatDir, _ := ioutil.TempDir(src_dir, "goflat") 111 goPath, _ := filepath.Abs(baseDir) 112 builder := &flatBuilder{ 113 baseDir: goflatDir, 114 flat: &Flat{ 115 GoTemplate: template, 116 goPath: goPath, 117 }, 118 } 119 120 return builder, nil 121 } 122 123 func (builder *flatBuilder) defaultPipes() (string, error) { 124 content := strings.Replace(PipesGo, "package runtime", "package main", -1) 125 outFile := filepath.Join(builder.baseDir, nameGenerator()) 126 err := ioutil.WriteFile(outFile, []byte(content), 0666) 127 if err != nil { 128 return "", err 129 } 130 return outFile, nil 131 } 132 133 func nameGenerator() string { 134 var alpha = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789" 135 136 size := 10 137 buf := make([]byte, size) 138 for i := 0; i < size; i++ { 139 buf[i] = alpha[rand.Intn(len(alpha))] 140 } 141 return string(buf) + ".go" 142 } 143 144 const ( 145 //ErrMissingOnDisk Expected error for accessing invalid file or directory 146 ErrMissingOnDisk = "(file or directory is missing)" 147 )