2017-07-19 22:06:43 +02:00
|
|
|
package commands
|
2017-06-18 22:54:58 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
yaml "gopkg.in/yaml.v2"
|
|
|
|
|
2017-07-07 00:18:26 +02:00
|
|
|
"github.com/montanaflynn/stats"
|
2017-06-22 17:02:32 +02:00
|
|
|
"github.com/osteele/gojekyll/pages"
|
2017-06-22 23:37:46 +02:00
|
|
|
"github.com/osteele/gojekyll/server"
|
2017-07-04 15:09:36 +02:00
|
|
|
"github.com/osteele/gojekyll/site"
|
2017-07-09 22:17:20 +02:00
|
|
|
"github.com/osteele/gojekyll/utils"
|
2017-07-03 15:37:14 +02:00
|
|
|
"github.com/osteele/liquid"
|
2017-06-18 22:54:58 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// main sets this
|
|
|
|
var commandStartTime = time.Now()
|
|
|
|
|
2017-07-04 15:09:36 +02:00
|
|
|
func buildCommand(site *site.Site) error {
|
2017-07-17 14:00:13 +02:00
|
|
|
watch := site.Config().Watch
|
|
|
|
|
2017-07-03 19:16:25 +02:00
|
|
|
logger.path("Destination:", site.DestDir())
|
|
|
|
logger.label("Generating...", "")
|
2017-07-17 14:00:13 +02:00
|
|
|
count, err := site.Build()
|
2017-07-15 03:19:01 +02:00
|
|
|
switch {
|
|
|
|
case err == nil:
|
|
|
|
elapsed := time.Since(commandStartTime)
|
|
|
|
logger.label("", "wrote %d files in %.2fs.", count, elapsed.Seconds())
|
|
|
|
case watch:
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
default:
|
2017-06-18 22:54:58 +02:00
|
|
|
return err
|
|
|
|
}
|
2017-07-15 03:19:01 +02:00
|
|
|
|
2017-07-15 15:44:22 +02:00
|
|
|
// FIXME the watch will miss files that changed during the first build
|
|
|
|
|
2017-07-15 03:19:01 +02:00
|
|
|
// server watch is implemented inside Server.Run, in contrast to this command
|
|
|
|
if watch {
|
2017-07-17 14:00:13 +02:00
|
|
|
events, err := site.WatchRebuild()
|
2017-07-15 03:19:01 +02:00
|
|
|
if err != nil {
|
2017-07-15 14:59:19 +02:00
|
|
|
return err
|
2017-07-15 03:19:01 +02:00
|
|
|
}
|
2017-07-25 15:29:38 +02:00
|
|
|
logger.label("Auto-regeneration:", "enabled for %q", site.SourceDir())
|
2017-07-15 14:59:19 +02:00
|
|
|
for event := range events {
|
|
|
|
fmt.Print(event)
|
2017-07-15 03:19:01 +02:00
|
|
|
}
|
2017-07-23 16:28:04 +02:00
|
|
|
} else {
|
|
|
|
logger.label("Auto-regeneration:", "disabled. Use --watch to enable.")
|
2017-07-15 03:19:01 +02:00
|
|
|
}
|
2017-07-15 14:59:19 +02:00
|
|
|
return nil
|
2017-07-15 03:19:01 +02:00
|
|
|
}
|
|
|
|
|
2017-07-04 15:09:36 +02:00
|
|
|
func cleanCommand(site *site.Site) error {
|
2017-07-03 19:16:25 +02:00
|
|
|
logger.label("Cleaner:", "Removing %s...", site.DestDir())
|
2017-07-17 14:00:13 +02:00
|
|
|
return site.Clean()
|
2017-07-02 01:42:48 +02:00
|
|
|
}
|
|
|
|
|
2017-07-06 16:43:43 +02:00
|
|
|
func benchmarkCommand() (err error) {
|
|
|
|
startTime := time.Now()
|
2017-07-07 21:48:31 +02:00
|
|
|
samples := []float64{}
|
2017-07-07 00:18:26 +02:00
|
|
|
for i := 0; time.Since(startTime) < 10*time.Second; i++ {
|
2017-07-07 21:48:31 +02:00
|
|
|
sampleStart := time.Now()
|
2017-07-17 14:00:13 +02:00
|
|
|
site, err := loadSite(*source, options)
|
2017-07-06 16:43:43 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2017-06-19 00:54:08 +02:00
|
|
|
}
|
2017-07-17 14:00:13 +02:00
|
|
|
_, err = site.Build()
|
2017-06-19 15:15:52 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-07-07 21:48:31 +02:00
|
|
|
dur := time.Since(sampleStart).Seconds()
|
|
|
|
samples = append(samples, dur)
|
|
|
|
quiet = true
|
|
|
|
fmt.Printf("Run #%d; %.1fs elapsed\n", i+1, time.Since(commandStartTime).Seconds())
|
2017-06-19 15:15:52 +02:00
|
|
|
}
|
2017-07-07 21:48:31 +02:00
|
|
|
median, _ := stats.Median(samples)
|
|
|
|
stddev, _ := stats.StandardDeviationSample(samples)
|
|
|
|
fmt.Printf("%d samples @ %.2fs ± %.2fs\n", len(samples), median, stddev)
|
2017-06-19 00:54:08 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-07-04 15:09:36 +02:00
|
|
|
func routesCommand(site *site.Site) error {
|
2017-07-03 19:16:25 +02:00
|
|
|
logger.label("Routes:", "")
|
2017-06-18 22:54:58 +02:00
|
|
|
urls := []string{}
|
2017-06-29 01:00:01 +02:00
|
|
|
for u, p := range site.Routes {
|
2017-06-21 19:14:30 +02:00
|
|
|
if !(*dynamicRoutes && p.Static()) {
|
2017-06-18 22:54:58 +02:00
|
|
|
urls = append(urls, u)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sort.Strings(urls)
|
|
|
|
for _, u := range urls {
|
2017-07-09 01:57:41 +02:00
|
|
|
filename := site.Routes[u].SourcePath()
|
2017-06-22 16:37:31 +02:00
|
|
|
fmt.Printf(" %s -> %s\n", u, filename)
|
2017-06-18 22:54:58 +02:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-07-04 15:09:36 +02:00
|
|
|
func renderCommand(site *site.Site) error {
|
2017-06-29 17:00:59 +02:00
|
|
|
p, err := pageFromPathOrRoute(site, *renderPath)
|
2017-06-18 22:54:58 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-07-09 01:57:41 +02:00
|
|
|
logger.path("Render:", filepath.Join(site.SourceDir(), p.SourcePath()))
|
2017-07-03 19:16:25 +02:00
|
|
|
logger.label("URL:", p.Permalink())
|
|
|
|
logger.label("Content:", "")
|
2017-07-09 15:37:23 +02:00
|
|
|
return site.WriteDocument(os.Stdout, p)
|
2017-06-18 22:54:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// If path starts with /, it's a URL path. Else it's a file path relative
|
|
|
|
// to the site source directory.
|
2017-07-04 15:09:36 +02:00
|
|
|
func pageFromPathOrRoute(s *site.Site, path string) (pages.Document, error) {
|
2017-06-22 16:37:31 +02:00
|
|
|
if path == "" {
|
|
|
|
path = "/"
|
2017-06-18 22:54:58 +02:00
|
|
|
}
|
2017-06-22 16:37:31 +02:00
|
|
|
switch {
|
2017-06-22 16:42:57 +02:00
|
|
|
case strings.HasPrefix(path, "/"):
|
|
|
|
page, found := s.URLPage(path)
|
|
|
|
if !found {
|
2017-07-09 22:17:20 +02:00
|
|
|
return nil, utils.NewPathError("render", path, "the site does not include a file with this URL path")
|
2017-06-22 16:42:57 +02:00
|
|
|
}
|
|
|
|
return page, nil
|
2017-06-22 16:37:31 +02:00
|
|
|
default:
|
2017-07-01 23:46:18 +02:00
|
|
|
page, found := s.FilePathPage(path)
|
2017-06-22 16:37:31 +02:00
|
|
|
if !found {
|
2017-07-09 22:17:20 +02:00
|
|
|
return nil, utils.NewPathError("render", path, "no such file")
|
2017-06-18 22:54:58 +02:00
|
|
|
}
|
2017-06-22 16:37:31 +02:00
|
|
|
return page, nil
|
2017-06-18 22:54:58 +02:00
|
|
|
}
|
|
|
|
}
|
2017-07-03 15:37:14 +02:00
|
|
|
|
2017-07-15 03:19:01 +02:00
|
|
|
func serveCommand(site *site.Site) error {
|
|
|
|
server := server.Server{Site: site}
|
|
|
|
return server.Run(*open, func(label, value string) {
|
|
|
|
logger.label(label, value)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-07-14 01:08:23 +02:00
|
|
|
func variablesCommand(site *site.Site) (err error) {
|
2017-07-03 15:37:14 +02:00
|
|
|
var data interface{}
|
|
|
|
switch {
|
2017-07-03 19:03:45 +02:00
|
|
|
case strings.HasPrefix(*variablePath, "site"):
|
2017-07-11 18:03:52 +02:00
|
|
|
data, err = utils.FollowDots(site, strings.Split(*variablePath, ".")[1:])
|
2017-07-04 14:29:11 +02:00
|
|
|
if err != nil {
|
|
|
|
return
|
2017-07-03 19:03:45 +02:00
|
|
|
}
|
|
|
|
case *variablePath != "":
|
2017-07-04 14:29:11 +02:00
|
|
|
data, err = pageFromPathOrRoute(site, *variablePath)
|
2017-07-03 15:37:14 +02:00
|
|
|
if err != nil {
|
2017-07-04 14:29:11 +02:00
|
|
|
return
|
2017-07-03 15:37:14 +02:00
|
|
|
}
|
2017-07-03 19:03:45 +02:00
|
|
|
default:
|
|
|
|
data = site
|
|
|
|
}
|
2017-07-11 18:03:52 +02:00
|
|
|
b, err := yaml.Marshal(liquid.FromDrop(data))
|
2017-07-03 15:37:14 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-07-03 19:16:25 +02:00
|
|
|
logger.label("Variables:", "")
|
2017-07-03 15:37:14 +02:00
|
|
|
fmt.Println(string(b))
|
|
|
|
return nil
|
|
|
|
}
|
2017-07-14 01:08:23 +02:00
|
|
|
|
|
|
|
func versionCommand() error {
|
2017-07-18 15:34:54 +02:00
|
|
|
var d string
|
|
|
|
if !BuildTime.IsZero() {
|
|
|
|
d = BuildTime.Format(" (Build time: 2006-01-02T15:04)")
|
|
|
|
}
|
|
|
|
fmt.Printf("gojekyll version %s%s\n", Version, d)
|
2017-07-14 01:08:23 +02:00
|
|
|
return nil
|
|
|
|
}
|