diff options
author | Alan Pearce | 2025-01-26 11:52:12 +0100 |
---|---|---|
committer | Alan Pearce | 2025-01-26 13:38:16 +0100 |
commit | 7d9e98a0996eca0372e38cee4b8826d84a9ace2b (patch) | |
tree | 6ae88100a923012f04ec316a45990b6902140136 /internal/outputs | |
parent | 93c01942cb379b448dafab7ceffd78c005772928 (diff) | |
download | website-7d9e98a0996eca0372e38cee4b8826d84a9ace2b.tar.lz website-7d9e98a0996eca0372e38cee4b8826d84a9ace2b.tar.zst website-7d9e98a0996eca0372e38cee4b8826d84a9ace2b.zip |
refactor outputs->storage for generalisation
Diffstat (limited to 'internal/outputs')
-rw-r--r-- | internal/outputs/files.go | 212 |
1 files changed, 0 insertions, 212 deletions
diff --git a/internal/outputs/files.go b/internal/outputs/files.go deleted file mode 100644 index e8da259..0000000 --- a/internal/outputs/files.go +++ /dev/null @@ -1,212 +0,0 @@ -package outputs - -import ( - "compress/gzip" - "context" - "io" - "io/fs" - "os" - "path" - "path/filepath" - - "go.alanpearce.eu/x/log" - - "github.com/a-h/templ" - "github.com/andybalholm/brotli" - "gitlab.com/tozd/go/errors" -) - -const ( - gzipLevel = 6 - brotliLevel = 9 -) - -type FilesOutput struct { - outputDirectory string - options *Options - log *log.Logger -} - -type Options struct { - CompressFiles bool -} - -func NewFilesOutput(outputDirectory string, logger *log.Logger, opts *Options) *FilesOutput { - return &FilesOutput{ - outputDirectory: outputDirectory, - options: opts, - log: logger, - } -} - -func (f *FilesOutput) CopyRecursive(src string) error { - return filepath.WalkDir(src, func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - rel, err := filepath.Rel(src, path) - if err != nil { - return err - } - if d.IsDir() { - return f.mkdirp(rel) - } - - sf, err := os.Open(path) - if err != nil { - return err - } - defer sf.Close() - df, err := f.openFileAndVariants(filepath.Join(f.outputDirectory, rel)) - if err != nil { - return err - } - defer df.Close() - if _, err := io.Copy(df, sf); err != nil { - return err - } - - return nil - }) -} - -func (f *FilesOutput) Open(filename string) (io.ReadCloser, error) { - return os.Open(filepath.Join(f.outputDirectory, filename)) -} - -func (f *FilesOutput) OutputToFile(output io.Reader, filename string) error { - fn := path.Join(f.outputDirectory, filename) - if err := f.mkdirp(filepath.Dir(filename)); err != nil { - return err - } - f.log.Debug("outputting file", "filename", fn) - file, err := f.openFileAndVariants(fn) - if err != nil { - return errors.WithMessage(err, "could not open output file") - } - defer file.Close() - - if _, err := io.Copy(file, output); err != nil { - return errors.WithMessage(err, "could not write output file") - } - - return nil -} - -func (f *FilesOutput) RenderToFile(component templ.Component, filename string) error { - fn := path.Join(f.outputDirectory, filename) - if err := f.mkdirp(filepath.Dir(filename)); err != nil { - return err - } - f.log.Debug("outputting file", "filename", filename) - file, err := f.openFileAndVariants(fn) - if err != nil { - return errors.WithMessage(err, "could not open output file") - } - defer file.Close() - - if err := component.Render(context.TODO(), file); err != nil { - return errors.WithMessage(err, "could not write output file") - } - - return nil -} - -func (f *FilesOutput) WriterToFile(writer io.WriterTo, filename string) error { - fn := path.Join(f.outputDirectory, filename) - if err := f.mkdirp(filepath.Dir(filename)); err != nil { - return err - } - f.log.Debug("outputting file", "filename", fn) - file, err := f.openFileAndVariants(fn) - if err != nil { - return errors.WithMessage(err, "could not open output file") - } - defer file.Close() - - if _, err := writer.WriteTo(file); err != nil { - return errors.WithMessage(err, "could not write output file") - } - - return nil -} - -type MultiWriteCloser struct { - writers []io.WriteCloser - multiWriter io.Writer -} - -func (mw *MultiWriteCloser) Write(p []byte) (n int, err error) { - return mw.multiWriter.Write(p) -} - -func (mw *MultiWriteCloser) Close() error { - var lastErr error - for _, w := range mw.writers { - err := w.Close() - if err != nil { - lastErr = err - } - } - - return lastErr -} - -func openFileWrite(filename string) (*os.File, error) { - return os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) -} - -func openFileGz(filename string) (*gzip.Writer, error) { - filenameGz := filename + ".gz" - f, err := openFileWrite(filenameGz) - if err != nil { - return nil, err - } - - return gzip.NewWriterLevel(f, gzipLevel) -} - -func openFileBrotli(filename string) (*brotli.Writer, error) { - filenameBrotli := filename + ".br" - f, err := openFileWrite(filenameBrotli) - if err != nil { - return nil, err - } - - return brotli.NewWriterLevel(f, brotliLevel), nil -} - -func multiOpenFile(filename string) (*MultiWriteCloser, error) { - r, err := openFileWrite(filename) - if err != nil { - return nil, err - } - gz, err := openFileGz(filename) - if err != nil { - return nil, err - } - br, err := openFileBrotli(filename) - if err != nil { - return nil, err - } - - return &MultiWriteCloser{ - writers: []io.WriteCloser{r, gz, br}, - multiWriter: io.MultiWriter(r, gz, br), - }, nil -} - -func (f *FilesOutput) openFileAndVariants(filename string) (io.WriteCloser, error) { - if f.options.CompressFiles { - return multiOpenFile(filename) - } - - return openFileWrite(filename) -} - -func (f *FilesOutput) mkdirp(dir string) error { - f.log.Debug("creating directory", "dir", dir) - err := os.MkdirAll(path.Join(f.outputDirectory, dir), 0755) - - return errors.WithMessage(err, "could not create directory") -} |