github.com/JarrahG/buffalocli@v0.0.0-20230801092127-b85bfd5d395a/internal/genny/build/archived_assets.go (about)

     1  package build
     2  
     3  import (
     4  	"archive/zip"
     5  	"bytes"
     6  	"fmt"
     7  	"io"
     8  	"io/fs"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	"github.com/gobuffalo/genny/v2"
    13  	"github.com/gobuffalo/genny/v2/gogen/goimports"
    14  )
    15  
    16  func archivedAssets(opts *Options) (*genny.Generator, error) {
    17  	g := genny.New()
    18  
    19  	if err := opts.Validate(); err != nil {
    20  		return g, err
    21  	}
    22  
    23  	target := filepath.Join(filepath.Dir(opts.App.Bin), "assets.zip")
    24  	source := filepath.Join(opts.App.Root, "public", "assets")
    25  
    26  	g.RunFn(func(r *genny.Runner) error {
    27  		bb := &bytes.Buffer{}
    28  		archive := zip.NewWriter(bb)
    29  		defer archive.Close()
    30  
    31  		for _, f := range r.Disk.Files() {
    32  			rel, err := filepath.Rel(source, f.Name())
    33  			if err != nil {
    34  				continue
    35  			}
    36  
    37  			if strings.HasPrefix(rel, "..") {
    38  				continue
    39  			}
    40  
    41  			file, ok := f.(fs.File)
    42  			if !ok {
    43  				return fmt.Errorf("cannot process file %s: cast failed", f.Name())
    44  			}
    45  
    46  			info, err := file.Stat()
    47  			if err != nil {
    48  				return err
    49  			}
    50  
    51  			header, err := zip.FileInfoHeader(info)
    52  			if err != nil {
    53  				return err
    54  			}
    55  			header.Name = rel
    56  			header.Method = zip.Deflate
    57  
    58  			writer, err := archive.CreateHeader(header)
    59  			if err != nil {
    60  				return err
    61  			}
    62  
    63  			_, err = io.Copy(writer, file)
    64  			if err != nil {
    65  				return err
    66  			}
    67  		}
    68  		// We need to close the archive before passing the buffer to genny, otherwise the zip
    69  		// will be corrupted.
    70  		archive.Close()
    71  		if err := r.File(genny.NewFile(target, bb)); err != nil {
    72  			return err
    73  		}
    74  		opts.keep.Store(target, struct{}{})
    75  		return nil
    76  	})
    77  
    78  	g.RunFn(func(r *genny.Runner) error {
    79  		f, err := r.FindFile("actions/app.go")
    80  		if err != nil {
    81  			return err
    82  		}
    83  
    84  		opts.rollback.Store(f.Name(), f.String())
    85  		body := strings.Replace(f.String(), `app.ServeFiles("/assets"`, `// app.ServeFiles("/assets"`, 1)
    86  		body = strings.Replace(body, `app.ServeFiles("/"`, `// app.ServeFiles("/"`, 1)
    87  		f = genny.NewFileS(f.Name(), body)
    88  
    89  		// run goimports after to ensure we remove unneeded imports
    90  		// from actions/app.go
    91  		content := bytes.NewBufferString("")
    92  		gi := goimports.NewFromFiles(goimports.File{
    93  			Name: f.Name(),
    94  			In:   f,
    95  			Out:  content,
    96  		})
    97  
    98  		if err := gi.Run(); err != nil {
    99  			return err
   100  		}
   101  
   102  		return r.File(genny.NewFile(f.Name(), content))
   103  	})
   104  
   105  	return g, nil
   106  }