diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2017-01-10 10:55:03 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2017-02-04 11:37:25 +0700 |
commit | c71e1b106e6011d148cac899f83c4685dee33a22 (patch) | |
tree | c5c7090f0c2398c7771e4908ebcc97aa7714ffd2 /commands | |
parent | 0ada40591216572b0e4c6a8ab986b0aa4fb13c13 (diff) |
all: Refactor to nonglobal file systems
Updates #2701
Fixes #2951
Diffstat (limited to 'commands')
-rw-r--r-- | commands/benchmark.go | 5 | ||||
-rw-r--r-- | commands/gendoc.go | 4 | ||||
-rw-r--r-- | commands/genman.go | 4 | ||||
-rw-r--r-- | commands/hugo.go | 135 | ||||
-rw-r--r-- | commands/import_jekyll.go | 25 | ||||
-rw-r--r-- | commands/new.go | 71 | ||||
-rw-r--r-- | commands/new_test.go | 82 | ||||
-rw-r--r-- | commands/server.go | 19 | ||||
-rw-r--r-- | commands/undraft.go | 9 |
9 files changed, 198 insertions, 156 deletions
diff --git a/commands/benchmark.go b/commands/benchmark.go index a879e8941..42966c67a 100644 --- a/commands/benchmark.go +++ b/commands/benchmark.go @@ -49,10 +49,13 @@ func init() { func benchmark(cmd *cobra.Command, args []string) error { cfg, err := InitializeConfig(benchmarkCmd) + if err != nil { return err } + c := commandeer{cfg} + var memProf *os.File if memProfileFile != "" { memProf, err = os.Create(memProfileFile) @@ -79,7 +82,7 @@ func benchmark(cmd *cobra.Command, args []string) error { t := time.Now() for i := 0; i < benchmarkTimes; i++ { - if err = resetAndBuildSites(cfg, false); err != nil { + if err = c.resetAndBuildSites(false); err != nil { return err } } diff --git a/commands/gendoc.go b/commands/gendoc.go index 046d3839c..5ffd084e1 100644 --- a/commands/gendoc.go +++ b/commands/gendoc.go @@ -51,9 +51,9 @@ for rendering in Hugo.`, if !strings.HasSuffix(gendocdir, helpers.FilePathSeparator) { gendocdir += helpers.FilePathSeparator } - if found, _ := helpers.Exists(gendocdir, hugofs.Os()); !found { + if found, _ := helpers.Exists(gendocdir, hugofs.Os); !found { jww.FEEDBACK.Println("Directory", gendocdir, "does not exist, creating...") - hugofs.Os().MkdirAll(gendocdir, 0777) + hugofs.Os.MkdirAll(gendocdir, 0777) } now := time.Now().Format(time.RFC3339) prepender := func(filename string) string { diff --git a/commands/genman.go b/commands/genman.go index d1f54ae31..f7a3a424d 100644 --- a/commands/genman.go +++ b/commands/genman.go @@ -41,9 +41,9 @@ in the "man" directory under the current directory.`, if !strings.HasSuffix(genmandir, helpers.FilePathSeparator) { genmandir += helpers.FilePathSeparator } - if found, _ := helpers.Exists(genmandir, hugofs.Os()); !found { + if found, _ := helpers.Exists(genmandir, hugofs.Os); !found { jww.FEEDBACK.Println("Directory", genmandir, "does not exist, creating...") - hugofs.Os().MkdirAll(genmandir, 0777) + hugofs.Os.MkdirAll(genmandir, 0777) } cmd.Root().DisableAutoGenTag = true diff --git a/commands/hugo.go b/commands/hugo.go index f4204cad1..566e68603 100644 --- a/commands/hugo.go +++ b/commands/hugo.go @@ -40,6 +40,7 @@ import ( "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/fsync" + "github.com/spf13/hugo/deps" "github.com/spf13/hugo/helpers" "github.com/spf13/hugo/hugolib" "github.com/spf13/hugo/livereload" @@ -50,6 +51,10 @@ import ( "github.com/spf13/viper" ) +type commandeer struct { + deps.DepsCfg +} + // Hugo represents the Hugo sites to build. This variable is exported as it // is used by at least one external library (the Hugo caddy plugin). We should // provide a cleaner external API, but until then, this is it. @@ -119,12 +124,14 @@ Complete documentation is available at http://gohugo.io/.`, return err } + c := commandeer{cfg} + if buildWatch { viper.Set("disableLiveReload", true) - watchConfig(cfg) + c.watchConfig() } - return build(cfg) + return c.build() }, } @@ -268,9 +275,9 @@ func init() { } // InitializeConfig initializes a config file with sensible default configuration flags. -func InitializeConfig(subCmdVs ...*cobra.Command) (hugolib.DepsCfg, error) { +func InitializeConfig(subCmdVs ...*cobra.Command) (deps.DepsCfg, error) { - var cfg hugolib.DepsCfg + var cfg deps.DepsCfg if err := hugolib.LoadGlobalConfig(source, cfgFile); err != nil { return cfg, err @@ -323,34 +330,34 @@ func InitializeConfig(subCmdVs ...*cobra.Command) (hugolib.DepsCfg, error) { viper.Set("cacheDir", cacheDir) } + // Init file systems. This may be changed at a later point. + cfg.Fs = hugofs.NewDefault() + cacheDir = viper.GetString("cacheDir") if cacheDir != "" { if helpers.FilePathSeparator != cacheDir[len(cacheDir)-1:] { cacheDir = cacheDir + helpers.FilePathSeparator } - isDir, err := helpers.DirExists(cacheDir, hugofs.Source()) + isDir, err := helpers.DirExists(cacheDir, cfg.Fs.Source) utils.CheckErr(err) if !isDir { mkdir(cacheDir) } viper.Set("cacheDir", cacheDir) } else { - viper.Set("cacheDir", helpers.GetTempDir("hugo_cache", hugofs.Source())) + viper.Set("cacheDir", helpers.GetTempDir("hugo_cache", cfg.Fs.Source)) } jww.INFO.Println("Using config file:", viper.ConfigFileUsed()) - // Init file systems. This may be changed at a later point. - hugofs.InitDefaultFs() - themeDir := helpers.GetThemeDir() if themeDir != "" { - if _, err := hugofs.Source().Stat(themeDir); os.IsNotExist(err) { + if _, err := cfg.Fs.Source.Stat(themeDir); os.IsNotExist(err) { return cfg, newSystemError("Unable to find theme Directory:", themeDir) } } - themeVersionMismatch, minVersion := isThemeVsHugoVersionMismatch() + themeVersionMismatch, minVersion := isThemeVsHugoVersionMismatch(cfg.Fs.Source) if themeVersionMismatch { jww.ERROR.Printf("Current theme does not support Hugo version %s. Minimum version required is %s\n", @@ -447,12 +454,12 @@ func flagChanged(flags *flag.FlagSet, key string) bool { return flag.Changed } -func watchConfig(cfg hugolib.DepsCfg) { +func (c commandeer) watchConfig() { viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { jww.FEEDBACK.Println("Config file changed:", e.Name) // Force a full rebuild - utils.CheckErr(recreateAndBuildSites(cfg, true)) + utils.CheckErr(c.recreateAndBuildSites(true)) if !viper.GetBool("disableLiveReload") { // Will block forever trying to write to a channel that nobody is reading if livereload isn't initialized livereload.ForceRefresh() @@ -460,39 +467,40 @@ func watchConfig(cfg hugolib.DepsCfg) { }) } -func build(cfg hugolib.DepsCfg, watches ...bool) error { +func (c commandeer) build(watches ...bool) error { // Hugo writes the output to memory instead of the disk. // This is only used for benchmark testing. Cause the content is only visible // in memory. if renderToMemory { - hugofs.SetDestination(new(afero.MemMapFs)) + c.Fs.Destination = new(afero.MemMapFs) // Rendering to memoryFS, publish to Root regardless of publishDir. viper.Set("publishDir", "/") } - if err := copyStatic(); err != nil { + if err := c.copyStatic(); err != nil { return fmt.Errorf("Error copying static files to %s: %s", helpers.AbsPathify(viper.GetString("publishDir")), err) } watch := false if len(watches) > 0 && watches[0] { watch = true } - if err := buildSites(cfg, buildWatch || watch); err != nil { + if err := c.buildSites(buildWatch || watch); err != nil { return fmt.Errorf("Error building site: %s", err) } if buildWatch { jww.FEEDBACK.Println("Watching for changes in", helpers.AbsPathify(viper.GetString("contentDir"))) jww.FEEDBACK.Println("Press Ctrl+C to stop") - utils.CheckErr(newWatcher(cfg, 0)) + utils.CheckErr(c.newWatcher(0)) } return nil } -func getStaticSourceFs() afero.Fs { - source := hugofs.Source() - themeDir, err := helpers.GetThemeStaticDirPath() +func (c commandeer) getStaticSourceFs() afero.Fs { + source := c.Fs.Source + pathSpec := helpers.NewPathSpec(c.Fs, viper.GetViper()) + themeDir, err := pathSpec.GetThemeStaticDirPath() staticDir := helpers.GetStaticDirPath() + helpers.FilePathSeparator useTheme := true @@ -532,12 +540,12 @@ func getStaticSourceFs() afero.Fs { jww.INFO.Println("using a UnionFS for static directory comprised of:") jww.INFO.Println("Base:", themeDir) jww.INFO.Println("Overlay:", staticDir) - base := afero.NewReadOnlyFs(afero.NewBasePathFs(hugofs.Source(), themeDir)) - overlay := afero.NewReadOnlyFs(afero.NewBasePathFs(hugofs.Source(), staticDir)) + base := afero.NewReadOnlyFs(afero.NewBasePathFs(source, themeDir)) + overlay := afero.NewReadOnlyFs(afero.NewBasePathFs(source, staticDir)) return afero.NewCopyOnWriteFs(base, overlay) } -func copyStatic() error { +func (c commandeer) copyStatic() error { publishDir := helpers.AbsPathify(viper.GetString("publishDir")) + helpers.FilePathSeparator // If root, remove the second '/' @@ -546,7 +554,7 @@ func copyStatic() error { } // Includes both theme/static & /static - staticSourceFs := getStaticSourceFs() + staticSourceFs := c.getStaticSourceFs() if staticSourceFs == nil { jww.WARN.Println("No static directories found to sync") @@ -557,7 +565,7 @@ func copyStatic() error { syncer.NoTimes = viper.GetBool("noTimes") syncer.NoChmod = viper.GetBool("noChmod") syncer.SrcFs = staticSourceFs - syncer.DestFs = hugofs.Destination() + syncer.DestFs = c.Fs.Destination // Now that we are using a unionFs for the static directories // We can effectively clean the publishDir on initial sync syncer.Delete = viper.GetBool("cleanDestinationDir") @@ -572,7 +580,7 @@ func copyStatic() error { } // getDirList provides NewWatcher() with a list of directories to watch for changes. -func getDirList() []string { +func (c commandeer) getDirList() []string { var a []string dataDir := helpers.AbsPathify(viper.GetString("dataDir")) i18nDir := helpers.AbsPathify(viper.GetString("i18nDir")) @@ -621,7 +629,7 @@ func getDirList() []string { jww.ERROR.Printf("Cannot read symbolic link '%s', error was: %s", path, err) return nil } - linkfi, err := hugofs.Source().Stat(link) + linkfi, err := c.Fs.Source.Stat(link) if err != nil { jww.ERROR.Printf("Cannot stat '%s', error was: %s", link, err) return nil @@ -642,25 +650,25 @@ func getDirList() []string { return nil } - helpers.SymbolicWalk(hugofs.Source(), dataDir, walker) - helpers.SymbolicWalk(hugofs.Source(), helpers.AbsPathify(viper.GetString("contentDir")), walker) - helpers.SymbolicWalk(hugofs.Source(), i18nDir, walker) - helpers.SymbolicWalk(hugofs.Source(), helpers.AbsPathify(viper.GetString("layoutDir")), walker) + helpers.SymbolicWalk(c.Fs.Source, dataDir, walker) + helpers.SymbolicWalk(c.Fs.Source, helpers.AbsPathify(viper.GetString("contentDir")), walker) + helpers.SymbolicWalk(c.Fs.Source, i18nDir, walker) + helpers.SymbolicWalk(c.Fs.Source, helpers.AbsPathify(viper.GetString("layoutDir")), walker) - helpers.SymbolicWalk(hugofs.Source(), staticDir, walker) + helpers.SymbolicWalk(c.Fs.Source, staticDir, walker) if helpers.ThemeSet() { - helpers.SymbolicWalk(hugofs.Source(), filepath.Join(themesDir, "layouts"), walker) - helpers.SymbolicWalk(hugofs.Source(), filepath.Join(themesDir, "static"), walker) - helpers.SymbolicWalk(hugofs.Source(), filepath.Join(themesDir, "i18n"), walker) - helpers.SymbolicWalk(hugofs.Source(), filepath.Join(themesDir, "data"), walker) + helpers.SymbolicWalk(c.Fs.Source, filepath.Join(themesDir, "layouts"), walker) + helpers.SymbolicWalk(c.Fs.Source, filepath.Join(themesDir, "static"), walker) + helpers.SymbolicWalk(c.Fs.Source, filepath.Join(themesDir, "i18n"), walker) + helpers.SymbolicWalk(c.Fs.Source, filepath.Join(themesDir, "data"), walker) } return a } -func recreateAndBuildSites(cfg hugolib.DepsCfg, watching bool) (err error) { - if err := initSites(cfg); err != nil { +func (c commandeer) recreateAndBuildSites(watching bool) (err error) { + if err := c.initSites(); err != nil { return err } if !quiet { @@ -669,9 +677,9 @@ func recreateAndBuildSites(cfg hugolib.DepsCfg, watching bool) (err error) { return Hugo.Build(hugolib.BuildCfg{CreateSitesFromConfig: true, Watching: watching, PrintStats: !quiet}) } -func resetAndBuildSites(cfg hugolib.DepsCfg, watching bool) (err error) { - if err := initSites(cfg); err != nil { - return err +func (c commandeer) resetAndBuildSites(watching bool) (err error) { + if err = c.initSites(); err != nil { + return } if !quiet { jww.FEEDBACK.Println("Started building sites ...") @@ -679,12 +687,12 @@ func resetAndBuildSites(cfg hugolib.DepsCfg, watching bool) (err error) { return Hugo.Build(hugolib.BuildCfg{ResetState: true, Watching: watching, PrintStats: !quiet}) } -func initSites(cfg hugolib.DepsCfg) error { +func (c commandeer) initSites() error { if Hugo != nil { return nil } - h, err := hugolib.NewHugoSitesFromConfiguration(cfg) + h, err := hugolib.NewHugoSitesFromConfiguration(c.DepsCfg) if err != nil { return err @@ -694,8 +702,8 @@ func initSites(cfg hugolib.DepsCfg) error { return nil } -func buildSites(cfg hugolib.DepsCfg, watching bool) (err error) { - if err := initSites(cfg); err != nil { +func (c commandeer) buildSites(watching bool) (err error) { + if err := c.initSites(); err != nil { return err } if !quiet { @@ -704,19 +712,21 @@ func buildSites(cfg hugolib.DepsCfg, watching bool) (err error) { return Hugo.Build(hugolib.BuildCfg{Watching: watching, PrintStats: !quiet}) } -func rebuildSites(cfg hugolib.DepsCfg, events []fsnotify.Event) error { - if err := initSites(cfg); err != nil { +func (c commandeer) rebuildSites(events []fsnotify.Event) error { + if err := c.initSites(); err != nil { return err } return Hugo.Build(hugolib.BuildCfg{PrintStats: !quiet, Watching: true}, events...) } // newWatcher creates a new watcher to watch filesystem events. -func newWatcher(cfg hugolib.DepsCfg, port int) error { +func (c commandeer) newWatcher(port int) error { if runtime.GOOS == "darwin" { tweakLimit() } + pathSpec := helpers.NewPathSpec(c.Fs, viper.GetViper()) + watcher, err := watcher.New(1 * time.Second) var wg sync.WaitGroup @@ -728,7 +738,7 @@ func newWatcher(cfg hugolib.DepsCfg, port int) error { wg.Add(1) - for _, d := range getDirList() { + for _, d := range c.getDirList() { if d != "" { _ = watcher.Add(d) } @@ -793,12 +803,12 @@ func newWatcher(cfg hugolib.DepsCfg, port int) error { // recursively add new directories to watch list // When mkdir -p is used, only the top directory triggers an event (at least on OSX) if ev.Op&fsnotify.Create == fsnotify.Create { - if s, err := hugofs.Source().Stat(ev.Name); err == nil && s.Mode().IsDir() { - helpers.SymbolicWalk(hugofs.Source(), ev.Name, walkAdder) + if s, err := c.Fs.Source.Stat(ev.Name); err == nil && s.Mode().IsDir() { + helpers.SymbolicWalk(c.Fs.Source, ev.Name, walkAdder) } } - isstatic := strings.HasPrefix(ev.Name, helpers.GetStaticDirPath()) || (len(helpers.GetThemesDirPath()) > 0 && strings.HasPrefix(ev.Name, helpers.GetThemesDirPath())) + isstatic := strings.HasPrefix(ev.Name, helpers.GetStaticDirPath()) || (len(pathSpec.GetThemesDirPath()) > 0 && strings.HasPrefix(ev.Name, pathSpec.GetThemesDirPath())) if isstatic { staticEvents = append(staticEvents, ev) @@ -821,12 +831,12 @@ func newWatcher(cfg hugolib.DepsCfg, port int) error { if viper.GetBool("forceSyncStatic") { jww.FEEDBACK.Printf("Syncing all static files\n") - err := copyStatic() + err := c.copyStatic() if err != nil { utils.StopOnErr(err, fmt.Sprintf("Error copying static files to %s", publishDir)) } } else { - staticSourceFs := getStaticSourceFs() + staticSourceFs := c.getStaticSourceFs() if staticSourceFs == nil { jww.WARN.Println("No static directories found to sync") @@ -837,7 +847,7 @@ func newWatcher(cfg hugolib.DepsCfg, port int) error { syncer.NoTimes = viper.GetBool("noTimes") syncer.NoChmod = viper.GetBool("noChmod") syncer.SrcFs = staticSourceFs - syncer.DestFs = hugofs.Destination() + syncer.DestFs = c.Fs.Destination // prevent spamming the log on changes logger := helpers.NewDistinctFeedbackLogger() @@ -862,7 +872,7 @@ func newWatcher(cfg hugolib.DepsCfg, port int) error { fromPath := ev.Name // If we are here we already know the event took place in a static dir - relPath, err := helpers.MakeStaticPathRelative(fromPath) + relPath, err := pathSpec.MakeStaticPathRelative(fromPath) if err != nil { jww.ERROR.Println(err) continue @@ -882,7 +892,7 @@ func newWatcher(cfg hugolib.DepsCfg, port int) error { // If file doesn't exist in any static dir, remove it toRemove := filepath.Join(publishDir, relPath) logger.Println("File no longer exists in static dir, removing", toRemove) - hugofs.Destination().RemoveAll(toRemove) + c.Fs.Destination.RemoveAll(toRemove) } else if err == nil { // If file still exists, sync it logger.Println("Syncing", relPath, "to", publishDir) @@ -910,7 +920,7 @@ func newWatcher(cfg hugolib.DepsCfg, port int) error { // force refresh when more than one file if len(staticEvents) > 0 { for _, ev := range staticEvents { - path, _ := helpers.MakeStaticPathRelative(ev.Name) + path, _ := pathSpec.MakeStaticPathRelative(ev.Name) livereload.RefreshPath(path) } @@ -925,7 +935,7 @@ func newWatcher(cfg hugolib.DepsCfg, port int) error { const layout = "2006-01-02 15:04 -0700" jww.FEEDBACK.Println(time.Now().Format(layout)) - rebuildSites(cfg, dynamicEvents) + c.rebuildSites(dynamicEvents) if !buildWatch && !viper.GetBool("disableLiveReload") { // Will block forever trying to write to a channel that nobody is reading if livereload isn't initialized @@ -947,7 +957,7 @@ func newWatcher(cfg hugolib.DepsCfg, port int) error { http.HandleFunc("/livereload", livereload.Handler) } - go serve(port) + go c.serve(port) } wg.Wait() @@ -956,14 +966,13 @@ func newWatcher(cfg hugolib.DepsCfg, port int) error { // isThemeVsHugoVersionMismatch returns whether the current Hugo version is // less than the theme's min_version. -func isThemeVsHugoVersionMismatch() (mismatch bool, requiredMinVersion string) { +func isThemeVsHugoVersionMismatch(fs afero.Fs) (mismatch bool, requiredMinVersion string) { if !helpers.ThemeSet() { return } themeDir := helpers.GetThemeDir() - fs := hugofs.Source() path := filepath.Join(themeDir, "theme.toml") exists, err := helpers.Exists(path, fs) diff --git a/commands/import_jekyll.go b/commands/import_jekyll.go index 7e55e0670..151fffa8a 100644 --- a/commands/import_jekyll.go +++ b/commands/import_jekyll.go @@ -25,6 +25,7 @@ import ( "strings" "time" + "github.com/spf13/afero" "github.com/spf13/cast" "github.com/spf13/cobra" "github.com/spf13/hugo/helpers" @@ -122,7 +123,7 @@ func importFromJekyll(cmd *cobra.Command, args []string) error { return convertJekyllPost(site, path, relPath, targetDir, draft) } - err = helpers.SymbolicWalk(hugofs.Os(), jekyllRoot, callback) + err = helpers.SymbolicWalk(hugofs.Os, jekyllRoot, callback) if err != nil { return err @@ -137,7 +138,13 @@ func importFromJekyll(cmd *cobra.Command, args []string) error { // TODO: Consider calling doNewSite() instead? func createSiteFromJekyll(jekyllRoot, targetDir string, force bool) (*hugolib.Site, error) { - fs := hugofs.Source() + s, err := hugolib.NewSiteDefaultLang() + if err != nil { + return nil, err + } + + fs := s.Fs.Source + if exists, _ := helpers.Exists(targetDir, fs); exists { if isDir, _ := helpers.IsDir(targetDir, fs); !isDir { return nil, errors.New("Target path \"" + targetDir + "\" already exists but not a directory") @@ -150,7 +157,7 @@ func createSiteFromJekyll(jekyllRoot, targetDir string, force bool) (*hugolib.Si } } - jekyllConfig := loadJekyllConfig(jekyllRoot) + jekyllConfig := loadJekyllConfig(fs, jekyllRoot) // Crude test to make sure at least one of _drafts/ and _posts/ exists // and is not empty. @@ -177,16 +184,14 @@ func createSiteFromJekyll(jekyllRoot, targetDir string, force bool) (*hugolib.Si mkdir(targetDir, "data") mkdir(targetDir, "themes") - createConfigFromJekyll(targetDir, "yaml", jekyllConfig) + createConfigFromJekyll(fs, targetDir, "yaml", jekyllConfig) copyJekyllFilesAndFolders(jekyllRoot, filepath.Join(targetDir, "static")) - site := hugolib.NewSiteDefaultLang() - return site, nil + return s, nil } -func loadJekyllConfig(jekyllRoot string) map[string]interface{} { - fs := hugofs.Source() +func loadJekyllConfig(fs afero.Fs, jekyllRoot string) map[string]interface{} { path := filepath.Join(jekyllRoot, "_config.yml") exists, err := helpers.Exists(path, fs) @@ -218,7 +223,7 @@ func loadJekyllConfig(jekyllRoot string) map[string]interface{} { return c.(map[string]interface{}) } -func createConfigFromJekyll(inpath string, kind string, jekyllConfig map[string]interface{}) (err error) { +func createConfigFromJekyll(fs afero.Fs, inpath string, kind string, jekyllConfig map[string]interface{}) (err error) { title := "My New Hugo Site" baseURL := "http://example.org/" @@ -251,7 +256,7 @@ func createConfigFromJekyll(inpath string, kind string, jekyllConfig map[string] return err } - err = helpers.WriteToDisk(filepath.Join(inpath, "config."+kind), bytes.NewReader(by), hugofs.Source()) + err = helpers.WriteToDisk(filepath.Join(inpath, "config."+kind), bytes.NewReader(by), fs) if err != nil { return } diff --git a/commands/new.go b/commands/new.go index 0b6ada534..b4a2740f3 100644 --- a/commands/new.go +++ b/commands/new.go @@ -16,15 +16,18 @@ package commands import ( "bytes" "errors" + "fmt" "os" "path/filepath" "strings" "time" + "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/hugo/create" "github.com/spf13/hugo/helpers" "github.com/spf13/hugo/hugofs" + "github.com/spf13/hugo/hugolib" "github.com/spf13/hugo/parser" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" @@ -84,7 +87,9 @@ as you see fit.`, // NewContent adds new content to a Hugo site. func NewContent(cmd *cobra.Command, args []string) error { - if _, err := InitializeConfig(); err != nil { + cfg, err := InitializeConfig() + + if err != nil { return err } @@ -110,10 +115,16 @@ func NewContent(cmd *cobra.Command, args []string) error { kind = contentType } - return create.NewContent(hugofs.Source(), kind, createpath) + s, err := hugolib.NewSite(cfg) + + if err != nil { + return newSystemError(err) + } + + return create.NewContent(s, kind, createpath) } -func doNewSite(basepath string, force bool) error { +func doNewSite(fs *hugofs.Fs, basepath string, force bool) error { dirs := []string{ filepath.Join(basepath, "layouts"), filepath.Join(basepath, "content"), @@ -123,12 +134,12 @@ func doNewSite(basepath string, force bool) error { filepath.Join(basepath, "themes"), } - if exists, _ := helpers.Exists(basepath, hugofs.Source()); exists { - if isDir, _ := helpers.IsDir(basepath, hugofs.Source()); !isDir { + if exists, _ := helpers.Exists(basepath, fs.Source); exists { + if isDir, _ := helpers.IsDir(basepath, fs.Source); !isDir { return errors.New(basepath + " already exists but not a directory") } - isEmpty, _ := helpers.IsEmpty(basepath, hugofs.Source()) + isEmpty, _ := helpers.IsEmpty(basepath, fs.Source) switch { case !isEmpty && !force: @@ -137,7 +148,7 @@ func doNewSite(basepath string, force bool) error { case !isEmpty && force: all := append(dirs, filepath.Join(basepath, "config."+configFormat)) for _, path := range all { - if exists, _ := helpers.Exists(path, hugofs.Source()); exists { + if exists, _ := helpers.Exists(path, fs.Source); exists { return errors.New(path + " already exists") } } @@ -145,10 +156,12 @@ func doNewSite(basepath string, force bool) error { } for _, dir := range dirs { - hugofs.Source().MkdirAll(dir, 0777) + if err := fs.Source.MkdirAll(dir, 0777); err != nil { + return fmt.Errorf("Failed to create dir: %s", err) + } } - createConfig(basepath, configFormat) + createConfig(fs, basepath, configFormat) jww.FEEDBACK.Printf("Congratulations! Your new Hugo site is created in %s.\n\n", basepath) jww.FEEDBACK.Println(nextStepsText()) @@ -190,12 +203,14 @@ func NewSite(cmd *cobra.Command, args []string) error { forceNew, _ := cmd.Flags().GetBool("force") - return doNewSite(createpath, forceNew) + return doNewSite(hugofs.NewDefault(), createpath, forceNew) } // NewTheme creates a new Hugo theme. func NewTheme(cmd *cobra.Command, args []string) error { - if _, err := InitializeConfig(); err != nil { + cfg, err := InitializeConfig() + + if err != nil { return err } @@ -207,26 +222,26 @@ func NewTheme(cmd *cobra.Command, args []string) error { createpath := helpers.AbsPathify(filepath.Join(viper.GetString("themesDir"), args[0])) jww.INFO.Println("creating theme at", createpath) - if x, _ := helpers.Exists(createpath, hugofs.Source()); x { + if x, _ := helpers.Exists(createpath, cfg.Fs.Source); x { return newUserError(createpath, "already exists") } mkdir(createpath, "layouts", "_default") mkdir(createpath, "layouts", "partials") - touchFile(createpath, "layouts", "index.html") - touchFile(createpath, "layouts", "404.html") - touchFile(createpath, "layouts", "_default", "list.html") - touchFile(createpath, "layouts", "_default", "single.html") + touchFile(cfg.Fs.Source, createpath, "layouts", "index.html") + touchFile(cfg.Fs.Source, createpath, "layouts", "404.html") + touchFile(cfg.Fs.Source, createpath, "layouts", "_default", "list.html") + touchFile(cfg.Fs.Source, createpath, "layouts", "_default", "single.html") - touchFile(createpath, "layouts", "partials", "header.html") - touchFile(createpath, "layouts", "partials", "footer.html") + touchFile(cfg.Fs.Source, createpath, "layouts", "partials", "header.html") + touchFile(cfg.Fs.Source, createpath, "layouts", "partials", "footer.html") mkdir(createpath, "archetypes") archDefault := []byte("+++\n+++\n") - err := helpers.WriteToDisk(filepath.Join(createpath, "archetypes", "default.md"), bytes.NewReader(archDefault), hugofs.Source()) + err = helpers.WriteToDisk(filepath.Join(createpath, "archetypes", "default.md"), bytes.NewReader(archDefault), cfg.Fs.Source) if err != nil { return err } @@ -256,12 +271,12 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. `) - err = helpers.WriteToDisk(filepath.Join(createpath, "LICENSE.md"), bytes.NewReader(by), hugofs.Source()) + err = helpers.WriteToDisk(filepath.Join(createpath, "LICENSE.md"), bytes.NewReader(by), cfg.Fs.Source) if err != nil { return err } - createThemeMD(createpath) + createThemeMD(cfg.Fs, createpath) return nil } @@ -275,16 +290,16 @@ func mkdir(x ...string) { } } -func touchFile(x ...string) { +func touchFile(fs afero.Fs, x ...string) { inpath := filepath.Join(x...) mkdir(filepath.Dir(inpath)) - err := helpers.WriteToDisk(inpath, bytes.NewReader([]byte{}), hugofs.Source()) + err := helpers.WriteToDisk(inpath, bytes.NewReader([]byte{}), fs) if err != nil { jww.FATAL.Fatalln(err) } } -func createThemeMD(inpath string) (err error) { +func createThemeMD(fs *hugofs.Fs, inpath string) (err error) { by := []byte(`# theme.toml template for a Hugo theme # See https://github.com/spf13/hugoThemes#themetoml for an example @@ -309,7 +324,7 @@ min_version = 0.18 repo = "" `) - err = helpers.WriteToDisk(filepath.Join(inpath, "theme.toml"), bytes.NewReader(by), hugofs.Source()) + err = helpers.WriteToDisk(filepath.Join(inpath, "theme.toml"), bytes.NewReader(by), fs.Source) if err != nil { return } @@ -320,7 +335,7 @@ min_version = 0.18 func newContentPathSection(path string) (string, string) { // Forward slashes is used in all examples. Convert if needed. // Issue #1133 - createpath := strings.Replace(path, "/", helpers.FilePathSeparator, -1) + createpath := filepath.FromSlash(path) var section string // assume the first directory is the section (kind) if strings.Contains(createpath[1:], helpers.FilePathSeparator) { @@ -330,7 +345,7 @@ func newContentPathSection(path string) (string, string) { return createpath, section } -func createConfig(inpath string, kind string) (err error) { +func createConfig(fs *hugofs.Fs, inpath string, kind string) (err error) { in := map[string]interface{}{ |