shithub: hugo

ref: 94d7fe52f87a3188a27767433e7a07f5ada84988
dir: /commands/hugo.go/

View raw version
// Copyright © 2013 Steve Francia <[email protected]>.
//
// Licensed under the Simple Public 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://opensource.org/licenses/Simple-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 commands

import (
	"fmt"
	"github.com/mostafah/fsync"
	"github.com/spf13/cobra"
	"github.com/spf13/hugo/hugolib"
	"log"
	"os"
	"path/filepath"
	"time"
)

var Config *hugolib.Config
var HugoCmd = &cobra.Command{
	Use:   "hugo",
	Short: "Hugo is a very fast static site generator",
	Long: `A Fast and Flexible Static Site Generator built with
love by spf13 and friends in Go.

Complete documentation is available at http://hugo.spf13.com`,
	Run: build,
}

var Hugo *cobra.Commander
var BuildWatch, Draft, UglyUrls, Verbose bool
var Source, Destination, BaseUrl, CfgFile string

func Execute() {
	AddCommands()
	Hugo := HugoCmd.ToCommander()
	Hugo.Execute()
}

func AddCommands() {
	HugoCmd.AddCommand(serverCmd)
	HugoCmd.AddCommand(version)
	HugoCmd.AddCommand(check)
	HugoCmd.AddCommand(benchmark)
}

func init() {
	HugoCmd.PersistentFlags().BoolVarP(&Draft, "build-drafts", "D", false, "include content marked as draft")
	HugoCmd.PersistentFlags().StringVarP(&Source, "source", "s", "", "filesystem path to read files relative from")
	HugoCmd.PersistentFlags().StringVarP(&Destination, "destination", "d", "", "filesystem path to write files to")
	HugoCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
	HugoCmd.PersistentFlags().BoolVar(&UglyUrls, "uglyurls", false, "if true, use /filename.html instead of /filename/")
	HugoCmd.PersistentFlags().StringVarP(&BaseUrl, "base-url", "b", "", "hostname (and path) to the root eg. http://spf13.com/")
	HugoCmd.PersistentFlags().StringVar(&CfgFile, "config", "", "config file (default is path/config.yaml|json|toml)")
	HugoCmd.Flags().BoolVarP(&BuildWatch, "watch", "w", false, "watch filesystem for changes and recreate as needed")
}

func InitializeConfig() {
	Config = hugolib.SetupConfig(&CfgFile, &Source)
	Config.BuildDrafts = Draft
	Config.UglyUrls = UglyUrls
	Config.Verbose = Verbose
	if BaseUrl != "" {
		Config.BaseUrl = BaseUrl
	}
	if Destination != "" {
		Config.PublishDir = Destination
	}
}

func build(cmd *cobra.Command, args []string) {
	InitializeConfig()

	err := copyStatic()
	if err != nil {
		log.Fatalf("Error copying static files to %s: %v", Config.GetAbsPath(Config.PublishDir), err)
	}
	if _, err := buildSite(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}

	// Does this even make sense without the server setting?
	//if BuildWatch {
	//fmt.Println("Watching for changes in", Config.GetAbsPath(Config.ContentDir))
	//_, err = buildSite()
	//if err != nil {
	//fmt.Println(err)
	//os.Exit(-1)
	//}
	//}
}

func copyStatic() error {
	// Copy Static to Destination
	return fsync.Sync(Config.GetAbsPath(Config.PublishDir+"/"), Config.GetAbsPath(Config.StaticDir+"/"))
}

func getDirList() []string {
	var a []string
	walker := func(path string, fi os.FileInfo, err error) error {
		if err != nil {
			fmt.Println("Walker: ", err)
			return nil
		}

		if fi.IsDir() {
			a = append(a, path)
		}
		return nil
	}

	filepath.Walk(Config.GetAbsPath(Config.ContentDir), walker)
	filepath.Walk(Config.GetAbsPath(Config.LayoutDir), walker)
	filepath.Walk(Config.GetAbsPath(Config.StaticDir), walker)

	return a
}

func buildSite() (site *hugolib.Site, err error) {
	startTime := time.Now()
	site = &hugolib.Site{Config: *Config}
	err = site.Build()
	if err != nil {
		return
	}
	site.Stats()
	fmt.Printf("in %v ms\n", int(1000*time.Since(startTime).Seconds()))
	return site, nil
}