diff options
Diffstat (limited to 'create/content.go')
-rw-r--r-- | create/content.go | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/create/content.go b/create/content.go new file mode 100644 index 000000000..6d022282e --- /dev/null +++ b/create/content.go @@ -0,0 +1,131 @@ +// Copyright 2016 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 provides functions to create new content. +package create + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + + "github.com/gohugoio/hugo/helpers" + "github.com/gohugoio/hugo/hugolib" + jww "github.com/spf13/jwalterweatherman" +) + +// NewContent creates a new content file in the content directory based upon the +// given kind, which is used to lookup an archetype. +func NewContent( + ps *helpers.PathSpec, + siteFactory func(filename string, siteUsed bool) (*hugolib.Site, error), kind, targetPath string) error { + ext := helpers.Ext(targetPath) + fs := ps.BaseFs.SourceFilesystems.Archetypes.Fs + + jww.INFO.Printf("attempting to create %q of %q of ext %q", targetPath, kind, ext) + + archetypeFilename := findArchetype(ps, kind, ext) + + // Building the sites can be expensive, so only do it if really needed. + siteUsed := false + + if archetypeFilename != "" { + f, err := fs.Open(archetypeFilename) + if err != nil { + return fmt.Errorf("failed to open archetype file: %s", err) + } + defer f.Close() + + if helpers.ReaderContains(f, []byte(".Site")) { + siteUsed = true + } + } + + s, err := siteFactory(targetPath, siteUsed) + if err != nil { + return err + } + + var content []byte + + content, err = executeArcheTypeAsTemplate(s, kind, targetPath, archetypeFilename) + if err != nil { + return err + } + + // The site may have multiple content dirs, and we currently do not know which contentDir the + // user wants to create this content in. We should improve on this, but we start by testing if the + // provided path points to an existing dir. If so, use it as is. + var contentPath string + var exists bool + targetDir := filepath.Dir(targetPath) + + if targetDir != "" && targetDir != "." { + exists, _ = helpers.Exists(targetDir, fs) + } + + if exists { + contentPath = targetPath + } else { + contentPath = s.PathSpec.AbsPathify(filepath.Join(s.Cfg.GetString("contentDir"), targetPath)) + } + + if err := helpers.SafeWriteToDisk(contentPath, bytes.NewReader(content), s.Fs.Source); err != nil { + return err + } + + jww.FEEDBACK.Println(contentPath, "created") + + editor := s.Cfg.GetString("newContentEditor") + if editor != "" { + jww.FEEDBACK.Printf("Editing %s with %q ...\n", targetPath, editor) + + cmd := exec.Command(editor, contentPath) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + return cmd.Run() + } + + return nil +} + +// FindArchetype takes a given kind/archetype of content and returns the path +// to the archetype in the archetype filesystem, blank if none found. +func findArchetype(ps *helpers.PathSpec, kind, ext string) (outpath string) { + fs := ps.BaseFs.Archetypes.Fs + + // If the new content isn't in a subdirectory, kind == "". + // Therefore it should be excluded otherwise `is a directory` + // error will occur. github.com/gohugoio/hugo/issues/411 + var pathsToCheck = []string{"default"} + + if ext != "" { + if kind != "" { + pathsToCheck = append([]string{kind + ext, "default" + ext}, pathsToCheck...) + } else { + pathsToCheck = append([]string{"default" + ext}, pathsToCheck...) + } + } + + for _, p := range pathsToCheck { + if exists, _ := helpers.Exists(p, fs); exists { + return p + } + } + + return "" +} |