2017-06-18 22:54:58 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2017-07-05 17:18:46 +02:00
|
|
|
"fmt"
|
2017-06-18 22:54:58 +02:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2017-07-06 16:43:43 +02:00
|
|
|
"reflect"
|
2017-07-02 15:48:30 +02:00
|
|
|
"runtime/pprof"
|
2017-06-18 22:54:58 +02:00
|
|
|
|
2017-07-05 17:18:46 +02:00
|
|
|
"github.com/osteele/gojekyll"
|
2017-07-01 20:55:50 +02:00
|
|
|
"github.com/osteele/gojekyll/config"
|
2017-07-04 15:09:36 +02:00
|
|
|
"github.com/osteele/gojekyll/site"
|
2017-06-21 19:14:30 +02:00
|
|
|
"gopkg.in/alecthomas/kingpin.v2"
|
2017-06-18 22:54:58 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// Command-line options
|
2017-06-21 19:14:30 +02:00
|
|
|
var (
|
2017-07-04 15:09:36 +02:00
|
|
|
buildOptions site.BuildOptions
|
2017-07-02 15:38:00 +02:00
|
|
|
configFlags = config.Flags{}
|
2017-07-02 15:48:30 +02:00
|
|
|
profile = false
|
2017-07-02 15:38:00 +02:00
|
|
|
quiet = false
|
2017-06-21 19:14:30 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2017-07-05 17:18:46 +02:00
|
|
|
app = kingpin.New("gojekyll", "a (somewhat) Jekyll-compatible blog generator")
|
2017-07-07 21:28:51 +02:00
|
|
|
source = app.Flag("source", "Source directory").Short('s').Default(".").ExistingDir()
|
2017-07-05 17:18:46 +02:00
|
|
|
_ = app.Flag("destination", "Destination directory").Short('d').Action(stringVar("destination", &configFlags.Destination)).String()
|
|
|
|
_ = app.Flag("drafts", "Render posts in the _drafts folder").Short('D').Action(boolVar("drafts", &configFlags.Drafts)).Bool()
|
|
|
|
_ = app.Flag("future", "Publishes posts with a future date").Action(boolVar("future", &configFlags.Future)).Bool()
|
|
|
|
_ = app.Flag("unpublished", "Render posts that were marked as unpublished").Action(boolVar("unpublished", &configFlags.Unpublished)).Bool()
|
|
|
|
versionFlag = app.Flag("version", "Print the name and version").Short('v').Bool()
|
2017-06-21 19:14:30 +02:00
|
|
|
|
2017-07-02 01:42:48 +02:00
|
|
|
build = app.Command("build", "Build your site").Alias("b")
|
|
|
|
clean = app.Command("clean", "Clean the site (removes site output) without building.")
|
|
|
|
|
2017-07-07 00:20:05 +02:00
|
|
|
benchmark = app.Command("benchmark", "Repeat build for ten seconds. Implies --profile.")
|
2017-06-21 19:14:30 +02:00
|
|
|
|
2017-07-03 19:03:45 +02:00
|
|
|
render = app.Command("render", "Render a file or URL path to standard output")
|
|
|
|
renderPath = render.Arg("PATH", "Path or URL").String()
|
2017-06-21 19:14:30 +02:00
|
|
|
|
|
|
|
routes = app.Command("routes", "Display site permalinks and associated files")
|
|
|
|
dynamicRoutes = routes.Flag("dynamic", "Only show routes to non-static files").Bool()
|
|
|
|
|
2017-07-03 19:03:45 +02:00
|
|
|
serve = app.Command("serve", "Serve your site locally").Alias("server").Alias("s")
|
|
|
|
open = serve.Flag("open-url", "Launch your site in a browser").Short('o').Bool()
|
2017-07-07 21:28:51 +02:00
|
|
|
_ = app.Flag("host", "Host to bind to").Short('H').Action(stringVar("host", &configFlags.Host)).String()
|
|
|
|
_ = serve.Flag("port", "Port to listen on").Short('P').Action(intVar("port", &configFlags.Port)).Int()
|
2017-07-03 19:03:45 +02:00
|
|
|
|
|
|
|
variables = app.Command("variables", "Display a file or URL path's variables").Alias("v").Alias("var").Alias("vars")
|
|
|
|
variablePath = variables.Arg("PATH", "Path, URL, site, or site...").String()
|
2017-07-05 17:18:46 +02:00
|
|
|
|
|
|
|
versionCmd = app.Command("version", "Print the name and version")
|
2017-06-21 19:14:30 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
2017-07-05 17:18:46 +02:00
|
|
|
app.HelpFlag.Short('h')
|
2017-07-02 15:48:30 +02:00
|
|
|
app.Flag("profile", "Create a Go pprof CPU profile").BoolVar(&profile)
|
2017-07-02 15:38:00 +02:00
|
|
|
app.Flag("quiet", "Silence (some) output.").Short('q').BoolVar(&quiet)
|
2017-06-21 19:14:30 +02:00
|
|
|
build.Flag("dry-run", "Dry run").Short('n').BoolVar(&buildOptions.DryRun)
|
|
|
|
}
|
2017-06-18 22:54:58 +02:00
|
|
|
|
|
|
|
func main() {
|
2017-07-12 01:23:42 +02:00
|
|
|
err := parseAndRun(os.Args[1:])
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintln(os.Stderr, err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
2017-07-04 14:29:11 +02:00
|
|
|
}
|
|
|
|
|
2017-07-12 01:23:42 +02:00
|
|
|
func parseAndRun(args []string) error {
|
2017-07-06 16:43:43 +02:00
|
|
|
if reflect.DeepEqual(args, []string{"--version"}) {
|
|
|
|
printVersion()
|
2017-07-12 01:23:42 +02:00
|
|
|
return nil
|
2017-07-06 16:43:43 +02:00
|
|
|
}
|
2017-07-04 14:29:11 +02:00
|
|
|
cmd := kingpin.MustParse(app.Parse(args))
|
2017-07-02 01:42:48 +02:00
|
|
|
if configFlags.Destination != nil {
|
|
|
|
dest, err := filepath.Abs(*configFlags.Destination)
|
2017-06-21 19:14:30 +02:00
|
|
|
app.FatalIfError(err, "")
|
2017-07-02 01:42:48 +02:00
|
|
|
configFlags.Destination = &dest
|
2017-06-18 22:54:58 +02:00
|
|
|
}
|
2017-07-02 15:38:00 +02:00
|
|
|
if buildOptions.DryRun {
|
|
|
|
buildOptions.Verbose = true
|
|
|
|
}
|
2017-07-12 01:23:42 +02:00
|
|
|
return run(cmd)
|
2017-06-21 19:14:30 +02:00
|
|
|
}
|
2017-07-02 01:42:48 +02:00
|
|
|
|
2017-07-05 17:18:46 +02:00
|
|
|
func printVersion() {
|
|
|
|
fmt.Printf("gojekyll %s\n", gojekyll.Version)
|
|
|
|
}
|
|
|
|
|
2017-07-04 14:29:11 +02:00
|
|
|
func run(cmd string) error { // nolint: gocyclo
|
2017-07-09 21:55:12 +02:00
|
|
|
if profile || cmd == benchmark.FullCommand() {
|
|
|
|
defer setupProfiling()()
|
2017-07-04 14:29:11 +02:00
|
|
|
}
|
2017-07-06 16:43:43 +02:00
|
|
|
if *versionFlag {
|
|
|
|
printVersion()
|
|
|
|
}
|
2017-07-05 17:18:46 +02:00
|
|
|
|
2017-07-06 16:43:43 +02:00
|
|
|
// These commands run *without* loading the site
|
2017-07-05 17:18:46 +02:00
|
|
|
switch cmd {
|
2017-07-06 16:43:43 +02:00
|
|
|
case benchmark.FullCommand():
|
|
|
|
return benchmarkCommand()
|
2017-07-05 17:18:46 +02:00
|
|
|
case versionCmd.FullCommand():
|
|
|
|
if !*versionFlag {
|
|
|
|
printVersion()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-07-01 20:55:50 +02:00
|
|
|
site, err := loadSite(*source, configFlags)
|
2017-06-21 19:14:30 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2017-06-18 22:54:58 +02:00
|
|
|
}
|
|
|
|
|
2017-07-06 16:43:43 +02:00
|
|
|
// These commands run after the site is loaded
|
2017-06-21 19:14:30 +02:00
|
|
|
switch cmd {
|
|
|
|
case build.FullCommand():
|
|
|
|
return buildCommand(site)
|
2017-07-02 01:42:48 +02:00
|
|
|
case clean.FullCommand():
|
|
|
|
return cleanCommand(site)
|
2017-06-21 19:14:30 +02:00
|
|
|
case render.FullCommand():
|
|
|
|
return renderCommand(site)
|
|
|
|
case routes.FullCommand():
|
|
|
|
return routesCommand(site)
|
|
|
|
case serve.FullCommand():
|
|
|
|
return serveCommand(site)
|
|
|
|
case variables.FullCommand():
|
|
|
|
return varsCommand(site)
|
2017-07-02 01:42:48 +02:00
|
|
|
default:
|
|
|
|
// kingpin should have provided help and exited before here
|
|
|
|
panic("unknown command")
|
2017-06-18 22:54:58 +02:00
|
|
|
}
|
2017-06-21 19:14:30 +02:00
|
|
|
}
|
2017-06-18 22:54:58 +02:00
|
|
|
|
2017-07-01 20:55:50 +02:00
|
|
|
// Load the site, and print the common banner settings.
|
2017-07-04 15:09:36 +02:00
|
|
|
func loadSite(source string, flags config.Flags) (*site.Site, error) {
|
|
|
|
site, err := site.FromDirectory(source, flags)
|
2017-06-21 19:14:30 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2017-07-03 19:16:25 +02:00
|
|
|
const configurationFileLabel = "Configuration file:"
|
2017-06-21 19:14:30 +02:00
|
|
|
if site.ConfigFile != nil {
|
2017-07-03 19:16:25 +02:00
|
|
|
logger.path(configurationFileLabel, *site.ConfigFile)
|
2017-06-21 19:14:30 +02:00
|
|
|
} else {
|
2017-07-03 19:16:25 +02:00
|
|
|
logger.label(configurationFileLabel, "none")
|
2017-06-21 19:14:30 +02:00
|
|
|
}
|
2017-07-03 19:16:25 +02:00
|
|
|
logger.label("Source:", site.SourceDir())
|
2017-07-09 01:57:41 +02:00
|
|
|
err = site.Read()
|
2017-06-21 19:14:30 +02:00
|
|
|
return site, err
|
2017-06-18 22:54:58 +02:00
|
|
|
}
|
2017-07-04 14:29:11 +02:00
|
|
|
|
2017-07-09 21:55:12 +02:00
|
|
|
func setupProfiling() func() {
|
2017-07-04 14:29:11 +02:00
|
|
|
profilePath := "gojekyll.prof"
|
|
|
|
logger.label("Profiling...", "")
|
|
|
|
f, err := os.Create(profilePath)
|
|
|
|
app.FatalIfError(err, "")
|
|
|
|
err = pprof.StartCPUProfile(f)
|
|
|
|
app.FatalIfError(err, "")
|
2017-07-09 21:55:12 +02:00
|
|
|
return func() {
|
2017-07-04 14:29:11 +02:00
|
|
|
pprof.StopCPUProfile()
|
|
|
|
err = f.Close()
|
|
|
|
app.FatalIfError(err, "")
|
|
|
|
logger.Info("Wrote", profilePath)
|
2017-07-09 21:55:12 +02:00
|
|
|
}
|
2017-07-04 14:29:11 +02:00
|
|
|
}
|