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  }