diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2019-01-02 13:58:32 +0300 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2019-01-02 16:25:37 +0300 |
commit | ce8a09a4c0661dece931ab1173e4f09e8e04aa38 (patch) | |
tree | 870372211e342312d0ab3034ee03285c6f698f9d /resources/resource_factories | |
parent | 669ada436787311cc5d02dae5b88e60a09adda58 (diff) |
resources: Move resource interfaces into its own package
Diffstat (limited to 'resources/resource_factories')
-rw-r--r-- | resources/resource_factories/bundler/bundler.go | 122 | ||||
-rw-r--r-- | resources/resource_factories/create/create.go | 65 |
2 files changed, 187 insertions, 0 deletions
diff --git a/resources/resource_factories/bundler/bundler.go b/resources/resource_factories/bundler/bundler.go new file mode 100644 index 000000000..ca0ccf86e --- /dev/null +++ b/resources/resource_factories/bundler/bundler.go @@ -0,0 +1,122 @@ +// Copyright 2019 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package bundler contains functions for concatenation etc. of Resource objects. +package bundler + +import ( + "fmt" + "io" + "path/filepath" + + "github.com/gohugoio/hugo/common/hugio" + "github.com/gohugoio/hugo/media" + "github.com/gohugoio/hugo/resources" + "github.com/gohugoio/hugo/resources/resource" +) + +// Client contains methods perform concatenation and other bundling related +// tasks to Resource objects. +type Client struct { + rs *resources.Spec +} + +// New creates a new Client with the given specification. +func New(rs *resources.Spec) *Client { + return &Client{rs: rs} +} + +type multiReadSeekCloser struct { + mr io.Reader + sources []hugio.ReadSeekCloser +} + +func (r *multiReadSeekCloser) Read(p []byte) (n int, err error) { + return r.mr.Read(p) +} + +func (r *multiReadSeekCloser) Seek(offset int64, whence int) (newOffset int64, err error) { + for _, s := range r.sources { + newOffset, err = s.Seek(offset, whence) + if err != nil { + return + } + } + return +} + +func (r *multiReadSeekCloser) Close() error { + for _, s := range r.sources { + s.Close() + } + return nil +} + +// Concat concatenates the list of Resource objects. +func (c *Client) Concat(targetPath string, r resource.Resources) (resource.Resource, error) { + // The CACHE_OTHER will make sure this will be re-created and published on rebuilds. + return c.rs.ResourceCache.GetOrCreate(resources.CACHE_OTHER, targetPath, func() (resource.Resource, error) { + var resolvedm media.Type + + // The given set of resources must be of the same Media Type. + // We may improve on that in the future, but then we need to know more. + for i, r := range r { + if i > 0 && r.MediaType().Type() != resolvedm.Type() { + return nil, fmt.Errorf("resources in Concat must be of the same Media Type, got %q and %q", r.MediaType().Type(), resolvedm.Type()) + } + resolvedm = r.MediaType() + } + + concatr := func() (hugio.ReadSeekCloser, error) { + var rcsources []hugio.ReadSeekCloser + for _, s := range r { + rcr, ok := s.(resource.ReadSeekCloserResource) + if !ok { + return nil, fmt.Errorf("resource %T does not implement resource.ReadSeekerCloserResource", s) + } + rc, err := rcr.ReadSeekCloser() + if err != nil { + // Close the already opened. + for _, rcs := range rcsources { + rcs.Close() + } + return nil, err + } + rcsources = append(rcsources, rc) + } + + readers := make([]io.Reader, len(rcsources)) + for i := 0; i < len(rcsources); i++ { + readers[i] = rcsources[i] + } + + mr := io.MultiReader(readers...) + + return &multiReadSeekCloser{mr: mr, sources: rcsources}, nil + } + + composite, err := c.rs.NewForFs( + c.rs.FileCaches.AssetsCache().Fs, + resources.ResourceSourceDescriptor{ + LazyPublish: true, + OpenReadSeekCloser: concatr, + RelTargetFilename: filepath.Clean(targetPath)}) + + if err != nil { + return nil, err + } + + return composite, nil + }) + +} diff --git a/resources/resource_factories/create/create.go b/resources/resource_factories/create/create.go new file mode 100644 index 000000000..dc565056d --- /dev/null +++ b/resources/resource_factories/create/create.go @@ -0,0 +1,65 @@ +// Copyright 2019 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package create contains functions for to create Resource objects. This will +// typically non-files. +package create + +import ( + "path/filepath" + + "github.com/spf13/afero" + + "github.com/gohugoio/hugo/common/hugio" + "github.com/gohugoio/hugo/resources" + "github.com/gohugoio/hugo/resources/resource" +) + +// Client contains methods to create Resource objects. +// tasks to Resource objects. +type Client struct { + rs *resources.Spec +} + +// New creates a new Client with the given specification. +func New(rs *resources.Spec) *Client { + return &Client{rs: rs} +} + +// Get creates a new Resource by opening the given filename in the given filesystem. +func (c *Client) Get(fs afero.Fs, filename string) (resource.Resource, error) { + filename = filepath.Clean(filename) + return c.rs.ResourceCache.GetOrCreate(resources.ResourceKeyPartition(filename), filename, func() (resource.Resource, error) { + return c.rs.NewForFs(fs, + resources.ResourceSourceDescriptor{ + LazyPublish: true, + SourceFilename: filename}) + }) + +} + +// FromString creates a new Resource from a string with the given relative target path. +func (c *Client) FromString(targetPath, content string) (resource.Resource, error) { + return c.rs.ResourceCache.GetOrCreate(resources.CACHE_OTHER, targetPath, func() (resource.Resource, error) { + return c.rs.NewForFs( + c.rs.FileCaches.AssetsCache().Fs, + resources.ResourceSourceDescriptor{ + LazyPublish: true, + OpenReadSeekCloser: func() (hugio.ReadSeekCloser, error) { + return hugio.NewReadSeekerNoOpCloserFromString(content), nil + }, + RelTargetFilename: filepath.Clean(targetPath)}) + + }) + +} |