summaryrefslogtreecommitdiffstats
path: root/create/content.go
diff options
context:
space:
mode:
Diffstat (limited to 'create/content.go')
-rw-r--r--create/content.go131
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 ""
+}