Skip to content

Commit

Permalink
Add Hugo Modules
Browse files Browse the repository at this point in the history
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
  • Loading branch information
bep committed Jun 18, 2019
1 parent 31c9c69 commit 12753e2
Show file tree
Hide file tree
Showing 86 changed files with 5,507 additions and 1,955 deletions.
27 changes: 14 additions & 13 deletions commands/commandeer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"os"
"path/filepath"
"regexp"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -388,21 +387,23 @@ func (c *commandeer) loadConfig(mustHaveConfigFile, running bool) error {

cfg.Logger.INFO.Println("Using config file:", config.ConfigFileUsed())

themeDir := c.hugo.PathSpec.GetFirstThemeDir()
if themeDir != "" {
if _, err := sourceFs.Stat(themeDir); os.IsNotExist(err) {
return newSystemError("Unable to find theme Directory:", themeDir)
// TODO(bep) mod
/*
themeDir := c.hugo.PathSpec.GetFirstThemeDir()
if themeDir != "" {
if _, err := sourceFs.Stat(themeDir); os.IsNotExist(err) {
return newSystemError("Unable to find theme Directory:", themeDir)
}
}
}
dir, themeVersionMismatch, minVersion := c.isThemeVsHugoVersionMismatch(sourceFs)

if themeVersionMismatch {
name := filepath.Base(dir)
cfg.Logger.ERROR.Printf("%s theme does not support Hugo version %s. Minimum version required is %s\n",
strings.ToUpper(name), hugo.CurrentVersion.ReleaseVersion(), minVersion)
}
dir, themeVersionMismatch, minVersion := c.isThemeVsHugoVersionMismatch(sourceFs)
if themeVersionMismatch {
name := filepath.Base(dir)
cfg.Logger.ERROR.Printf("%s theme does not support Hugo version %s. Minimum version required is %s\n",
strings.ToUpper(name), hugo.CurrentVersion.ReleaseVersion(), minVersion)
}
*/
return nil

}
20 changes: 14 additions & 6 deletions commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func (b *commandsBuilder) addAll() *commandsBuilder {
newImportCmd(),
newGenCmd(),
createReleaser(),
b.newModCmd(),
)

return b
Expand Down Expand Up @@ -189,9 +190,10 @@ Complete documentation is available at http://gohugo.io/.`,
}

type hugoBuilderCommon struct {
source string
baseURL string
environment string
source string
baseURL string
environment string
ignoreVendor bool

buildWatch bool

Expand Down Expand Up @@ -243,20 +245,26 @@ func (cc *hugoBuilderCommon) getEnvironment(isServer bool) string {
return hugo.EnvironmentProduction
}

func (cc *hugoBuilderCommon) handleCommonBuilderFlags(cmd *cobra.Command) {
cmd.PersistentFlags().StringVarP(&cc.source, "source", "s", "", "filesystem path to read files relative from")
cmd.PersistentFlags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{})
cmd.PersistentFlags().StringVarP(&cc.environment, "environment", "e", "", "build environment")
cmd.PersistentFlags().StringP("themesDir", "", "", "filesystem path to themes directory")
cmd.PersistentFlags().BoolP("ignoreVendor", "", false, "ignores any _vendor directory")
}

func (cc *hugoBuilderCommon) handleFlags(cmd *cobra.Command) {
cc.handleCommonBuilderFlags(cmd)
cmd.Flags().Bool("cleanDestinationDir", false, "remove files from destination not found in static directories")
cmd.Flags().BoolP("buildDrafts", "D", false, "include content marked as draft")
cmd.Flags().BoolP("buildFuture", "F", false, "include content with publishdate in the future")
cmd.Flags().BoolP("buildExpired", "E", false, "include expired content")
cmd.Flags().StringVarP(&cc.source, "source", "s", "", "filesystem path to read files relative from")
cmd.Flags().StringVarP(&cc.environment, "environment", "e", "", "build environment")
cmd.Flags().StringP("contentDir", "c", "", "filesystem path to content directory")
cmd.Flags().StringP("layoutDir", "l", "", "filesystem path to layout directory")
cmd.Flags().StringP("cacheDir", "", "", "filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/")
cmd.Flags().BoolP("ignoreCache", "", false, "ignores the cache directory")
cmd.Flags().StringP("destination", "d", "", "filesystem path to write files to")
cmd.Flags().StringSliceP("theme", "t", []string{}, "themes to use (located in /themes/THEMENAME/)")
cmd.Flags().StringP("themesDir", "", "", "filesystem path to themes directory")
cmd.Flags().StringVarP(&cc.baseURL, "baseURL", "b", "", "hostname (and path) to the root, e.g. http://spf13.com/")
cmd.Flags().Bool("enableGitInfo", false, "add Git revision, date and author info to the pages")
cmd.Flags().BoolVar(&cc.gc, "gc", false, "enable to run some cleanup tasks (remove unused cache files) after the build")
Expand Down
150 changes: 50 additions & 100 deletions commands/hugo.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ func initializeFlags(cmd *cobra.Command, cfg config.Provider) {
"forceSyncStatic",
"noTimes",
"noChmod",
"ignoreVendor",
"templateMetrics",
"templateMetricsHints",

Expand Down Expand Up @@ -309,13 +310,9 @@ func (c *commandeer) fullBuild() error {

cnt, err := c.copyStatic()
if err != nil {
if !os.IsNotExist(err) {
return errors.Wrap(err, "Error copying static files")
}
c.logger.INFO.Println("No Static directory found")
return errors.Wrap(err, "Error copying static files")
}
langCount = cnt
langCount = cnt
return nil
}
buildSitesFunc := func() error {
Expand Down Expand Up @@ -547,7 +544,11 @@ func (c *commandeer) serverBuild() error {
}

func (c *commandeer) copyStatic() (map[string]uint64, error) {
return c.doWithPublishDirs(c.copyStaticTo)
m, err := c.doWithPublishDirs(c.copyStaticTo)
if err == nil || os.IsNotExist(err) {
return m, nil
}
return m, err
}

func (c *commandeer) doWithPublishDirs(f func(sourceFs *filesystems.SourceFilesystem) (uint64, error)) (map[string]uint64, error) {
Expand Down Expand Up @@ -609,7 +610,8 @@ func (c *commandeer) copyStaticTo(sourceFs *filesystems.SourceFilesystem) (uint6

syncer := fsync.NewSyncer()
syncer.NoTimes = c.Cfg.GetBool("noTimes")
syncer.NoChmod = c.Cfg.GetBool("noChmod")
// TODO(bep) mod Go module cache has 0555 directories.
syncer.NoChmod = true // c.Cfg.GetBool("noChmod")
syncer.SrcFs = fs
syncer.DestFs = c.Fs.Destination
// Now that we are using a unionFs for the static directories
Expand Down Expand Up @@ -652,120 +654,62 @@ func (c *commandeer) timeTrack(start time.Time, name string) {

// getDirList provides NewWatcher() with a list of directories to watch for changes.
func (c *commandeer) getDirList() ([]string, error) {
var a []string
var dirnames []string

// To handle nested symlinked content dirs
var seen = make(map[string]bool)
var nested []string

newWalker := func(allowSymbolicDirs bool) func(path string, fi os.FileInfo, err error) error {
return func(path string, fi os.FileInfo, err error) error {
if err != nil {
if os.IsNotExist(err) {
return nil
}

c.logger.ERROR.Println("Walker: ", err)
return nil
}

// Skip .git directories.
// Related to https://github.com/gohugoio/hugo/issues/3468.
if fi.Name() == ".git" {
return nil
}

if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
link, err := filepath.EvalSymlinks(path)
if err != nil {
c.logger.ERROR.Printf("Cannot read symbolic link '%s', error was: %s", path, err)
return nil
}
linkfi, err := helpers.LstatIfPossible(c.Fs.Source, link)
if err != nil {
c.logger.ERROR.Printf("Cannot stat %q: %s", link, err)
return nil
}
if !allowSymbolicDirs && !linkfi.Mode().IsRegular() {
c.logger.ERROR.Printf("Symbolic links for directories not supported, skipping %q", path)
return nil
}

if allowSymbolicDirs && linkfi.IsDir() {
// afero.Walk will not walk symbolic links, so wee need to do it.
if !seen[path] {
seen[path] = true
nested = append(nested, path)
}
return nil
}

fi = linkfi
}
// var nested []string TODO(bep) mod

if fi.IsDir() {
if fi.Name() == ".git" ||
fi.Name() == "node_modules" || fi.Name() == "bower_components" {
return filepath.SkipDir
}
a = append(a, path)
}
walkFn := func(fi hugofs.FileMetaInfo, err error) error {
if err != nil {
c.logger.ERROR.Println("walker: ", err)
return nil
}
}

symLinkWalker := newWalker(true)
regularWalker := newWalker(false)
if fi.IsDir() {
if fi.Name() == ".git" ||
fi.Name() == "node_modules" || fi.Name() == "bower_components" {
return filepath.SkipDir
}

// SymbolicWalk will log anny ERRORs
// Also note that the Dirnames fetched below will contain any relevant theme
// directories.
for _, contentDir := range c.hugo.PathSpec.BaseFs.Content.Dirnames {
_ = helpers.SymbolicWalk(c.Fs.Source, contentDir, symLinkWalker)
}
dirnames = append(dirnames, fi.Meta().Filename())
}

for _, staticDir := range c.hugo.PathSpec.BaseFs.Data.Dirnames {
_ = helpers.SymbolicWalk(c.Fs.Source, staticDir, regularWalker)
}
return nil

for _, staticDir := range c.hugo.PathSpec.BaseFs.I18n.Dirnames {
_ = helpers.SymbolicWalk(c.Fs.Source, staticDir, regularWalker)
}

for _, staticDir := range c.hugo.PathSpec.BaseFs.Layouts.Dirnames {
_ = helpers.SymbolicWalk(c.Fs.Source, staticDir, regularWalker)
}
watchDirs := c.hugo.PathSpec.BaseFs.WatchDirs()
for _, watchDir := range watchDirs {

for _, staticFilesystem := range c.hugo.PathSpec.BaseFs.Static {
for _, staticDir := range staticFilesystem.Dirnames {
_ = helpers.SymbolicWalk(c.Fs.Source, staticDir, regularWalker)
w := hugofs.NewWalkwayFromFi(watchDir, walkFn)
if err := w.Walk(); err != nil {
c.logger.ERROR.Println("walker: ", err)
}
}

for _, assetDir := range c.hugo.PathSpec.BaseFs.Assets.Dirnames {
_ = helpers.SymbolicWalk(c.Fs.Source, assetDir, regularWalker)
}
// TODO(bep) mod
/*
if len(nested) > 0 {
for {
if len(nested) > 0 {
for {

toWalk := nested
nested = nested[:0]
toWalk := nested
nested = nested[:0]
for _, d := range toWalk {
_ = helpers.SymbolicWalk(c.Fs.Source, d, symLinkWalker)
}
for _, d := range toWalk {
_ = helpers.SymbolicWalk(c.Fs.Source, d, symLinkWalker)
}
if len(nested) == 0 {
break
if len(nested) == 0 {
break
}
}
}
}
*/

a = helpers.UniqueStrings(a)
sort.Strings(a)
dirnames = helpers.UniqueStrings(dirnames)
sort.Strings(dirnames)

return a, nil
return dirnames, nil
}

func (c *commandeer) buildSites() (err error) {
Expand Down Expand Up @@ -825,7 +769,13 @@ func (c *commandeer) fullRebuild() {
}

if !c.paused {
err := c.buildSites()
_, err := c.copyStatic()
if err != nil {
c.logger.ERROR.Println(err)
return
}

err = c.buildSites()
if err != nil {
c.logger.ERROR.Println(err)
} else if !c.h.buildWatch && !c.Cfg.GetBool("disableLiveReload") {
Expand Down
Loading

0 comments on commit 12753e2

Please sign in to comment.