github.com/jduhamel/gcli@v0.2.4-0.20151019142748-0d5307cd7e21/skeleton/main.go (about) 1 package skeleton 2 3 import ( 4 "io" 5 "path/filepath" 6 "strings" 7 "sync" 8 ) 9 10 // Skeleton stores meta data of skeleton 11 type Skeleton struct { 12 // Path is where skeleton is generated. 13 Path string 14 15 // If WithTest is true, also generate test code. 16 SkipTest bool 17 18 Framework *Framework 19 Executable *Executable 20 21 // ArtifactCh is channel for info output 22 ArtifactCh chan string 23 24 // ErrCh is channel for error output 25 ErrCh chan error 26 27 // Verbose enables logging output below INFO 28 Verbose bool 29 30 // LogWriter 31 LogWriter io.Writer 32 } 33 34 // Generate generates code files from tempalte files. 35 func (s *Skeleton) Generate() <-chan struct{} { 36 37 s.Debugf("Start generating") 38 39 // doneCh is used to tell task it done to parent function 40 doneCh := make(chan struct{}) 41 42 go func() { 43 44 // Start generating base files 45 doneBaseCh := s.generateBaseFiles() 46 47 // Start generating command files 48 doneCmdCh := s.generateCommandFiles() 49 50 <-doneBaseCh 51 <-doneCmdCh 52 53 doneCh <- struct{}{} 54 }() 55 56 return doneCh 57 } 58 59 func (s *Skeleton) generateBaseFiles() <-chan struct{} { 60 61 s.Debugf("Start generating base files") 62 63 // doneCh is used to tell task it done 64 doneCh := make(chan struct{}) 65 66 go func() { 67 68 var wg sync.WaitGroup 69 baseTmpls := CommonTemplates 70 baseTmpls = append(baseTmpls, s.Framework.BaseTemplates...) 71 for _, tmpl := range baseTmpls { 72 s.Debugf("Use tempalte file: %s, output path tempalte string: %s", 73 tmpl.Path, tmpl.OutputPathTmpl) 74 75 if s.SkipTest && strings.HasSuffix(tmpl.Path, "_test.go.tmpl") { 76 s.Debugf("Skip test tempalte file: %s", filepath.Base(tmpl.Path)) 77 continue 78 } 79 80 wg.Add(1) 81 go func(tmpl Template) { 82 defer wg.Done() 83 tmpl.OutputPathTmpl = filepath.Join(s.Path, tmpl.OutputPathTmpl) 84 outputPath, err := tmpl.Exec(s.Executable) 85 if err != nil { 86 s.ErrCh <- err 87 } 88 s.ArtifactCh <- outputPath 89 }(tmpl) 90 } 91 92 // Wait until all task is done 93 wg.Wait() 94 95 // Tell doneCh about finishing generating 96 doneCh <- struct{}{} 97 }() 98 99 return doneCh 100 } 101 102 func (s *Skeleton) generateCommandFiles() <-chan struct{} { 103 104 s.Debugf("Start generating command files") 105 106 // doneCh is used to tell task it done 107 doneCh := make(chan struct{}) 108 109 go func() { 110 var wg sync.WaitGroup 111 112 for _, cmd := range s.Executable.Commands { 113 wg.Add(1) 114 go func(cmd *Command) { 115 defer wg.Done() 116 for _, tmpl := range s.Framework.CommandTemplates { 117 118 s.Debugf("Use tempalte file: %s, output path tempalte string: %s", 119 tmpl.Path, tmpl.OutputPathTmpl) 120 if s.SkipTest && strings.HasSuffix(tmpl.Path, "_test.go.tmpl") { 121 s.Debugf("Skip test tempalte file: %s", tmpl.Path) 122 continue 123 } 124 125 tmpl.OutputPathTmpl = filepath.Join(s.Path, tmpl.OutputPathTmpl) 126 outputPath, err := tmpl.Exec(cmd) 127 if err != nil { 128 s.ErrCh <- err 129 } 130 s.ArtifactCh <- outputPath 131 } 132 }(cmd) 133 } 134 135 // Wait until all task is done. 136 wg.Wait() 137 138 doneCh <- struct{}{} 139 }() 140 141 return doneCh 142 }