1
0
mirror of https://github.com/danog/gojekyll.git synced 2024-11-30 04:09:00 +01:00

incremental pt. 1

This commit is contained in:
Oliver Steele 2017-07-25 09:29:38 -04:00
parent de57141230
commit 0b653d6b24
7 changed files with 57 additions and 33 deletions

View File

@ -144,14 +144,16 @@ Muzukashii:
- [x] Directory watch
- [ ] Commands
- [x] `build`
- [x] `--source`, `--destination`, `--drafts`, `--future`, `--unpublished`, `--watch`, `--force_polling`
- [ ] `--baseurl`, `--config`, `--incremental`, `--lsi`
- [x] `--source`, `--destination`, `--drafts`, `--future`, `--unpublished`
- [x] `--incremental`, `--watch`, `--force_polling`
- [ ] `--baseurl`, `--config`, `--lsi`
- [ ] `--limit-posts`, `JEKYLL_ENV=production` not planned
- [x] `clean`
- [x] `help`
- [x] `serve`
- [x] `--open-uri`, `--host`, `--port`, `watch`, `--force_polling`
- [ ] `--baseurl`, `--config`, `--incremental`
- [x] `--open-uri`, `--host`, `--port`
- [x] `--incremental`, `watch`, `--force_polling`
- [ ] `--baseurl`, `--config`
- [ ] `--detach`, `--ssl`-* not planned
- [ ] `doctor`, `import`, `new`, `new-theme` not planned
- [ ] Windows

View File

@ -45,7 +45,7 @@ func buildCommand(site *site.Site) error {
if err != nil {
return err
}
logger.label("Auto-regeneration:", "enabled for %q\n", site.SourceDir())
logger.label("Auto-regeneration:", "enabled for %q", site.SourceDir())
for event := range events {
fmt.Print(event)
}

View File

@ -48,9 +48,12 @@ func init() {
app.Flag("profile", "Create a Go pprof CPU profile").BoolVar(&profile)
app.Flag("quiet", "Silence (some) output.").Short('q').BoolVar(&quiet)
_ = app.Flag("verbose", "Print verbose output.").Short('V').Action(boolVar("verbose", &options.Verbose)).Bool()
app.Flag("force_polling", "Force watch to use polling").BoolVar(&options.ForcePolling)
build.Flag("dry-run", "Dry run").Short('n').BoolVar(&options.DryRun)
// these flags are just present on build and serve, but I don't see a DRY way to say this
app.Flag("incremental", "Enable incremental rebuild.").Short('I').Action(boolVar("incremental", &options.Incremental)).Bool()
app.Flag("force_polling", "Force watch to use polling").BoolVar(&options.ForcePolling)
// --watch has different defaults for build and serve
watchText := "Watch for changes and rebuild"
build.Flag("watch", watchText).Short('w').BoolVar(&options.Watch)

View File

@ -107,6 +107,11 @@ type collectionsMap struct {
Collections map[string]map[string]interface{}
}
// IsConfigPath returns true if its arguments is a site configuration file.
func (c *Config) IsConfigPath(rel string) bool {
return rel == "_config.yml"
}
// SourceDir returns the source directory as an absolute path.
func (c *Config) SourceDir() string {
return utils.MustAbs(c.Source)

View File

@ -7,17 +7,20 @@ import (
// Flags are applied after the configuration file is loaded.
// They are pointers to represent optional types, to tell whether they have been set.
type Flags struct {
// these are pointers so we can tell whether they've been set, and override
// the config file only if
Destination, Host *string
Drafts, Future, Unpublished, Verbose *bool
Port *int
// these aren't in the config file, so they can be treated more conventionally
// these are pointers so we can tell whether they've been set, and leave
// the config file alone if not
Destination, Host *string
Drafts, Future, Unpublished *bool
Incremental, Verbose *bool
Port *int
// these aren't in the config file, so make them actual values
DryRun, ForcePolling, Watch bool
}
// ApplyFlags overwrites the configuration with values from flags.
func (c *Config) ApplyFlags(f Flags) {
// anything you can do I can do meta
rs, rd := reflect.ValueOf(f), reflect.ValueOf(c).Elem()
rt := rs.Type()
for i, n := 0, rs.NumField(); i < n; i++ {

View File

@ -56,10 +56,27 @@ func (s *Site) processFilesEvent(fileset FilesEvent, messages chan<- interface{}
return r
}
// reloads and rebuilds the site; returns a copy and count
func (s *Site) rebuild(paths []string) (*Site, int, error) {
if s.requiresFullReload(paths) {
r, err := s.Reloaded(paths)
if err != nil {
return nil, 0, err
}
n, err := r.Build()
return r, n, err
}
return s, 0, nil
}
func (s *Site) requiresFullReload(paths []string) bool {
for _, path := range paths {
switch {
case path == "_config.yml":
case s.config.IsConfigPath(path):
return true
case s.Exclude(path):
return false
case !s.config.Incremental:
return true
case strings.HasPrefix(path, s.config.DataDir):
return true
@ -70,29 +87,23 @@ func (s *Site) requiresFullReload(paths []string) bool {
return false
}
// reloads and rebuilds the site; returns a copy and count
func (s *Site) rebuild(paths []string) (r *Site, n int, err error) {
r, err = s.Reloaded(paths)
if err != nil {
return
}
n, err = r.Build()
return
}
// relativize and de-dup filenames, and filter to those that affect the build
func (s *Site) sitePaths(filenames []string) []string {
func (s *Site) affectsBuildFilter(filenames []string) []string {
var (
paths = make([]string, 0, len(filenames))
seen = map[string]bool{}
result = make([]string, 0, len(filenames))
seen = map[string]bool{}
)
loop:
for _, path := range filenames {
if path == "_config.yml" || !s.Exclude(path) {
if !seen[path] {
seen[path] = true
paths = append(paths, path)
}
switch {
case s.config.IsConfigPath(path):
case s.Exclude(path):
continue loop
case seen[path]:
continue loop
}
seen[path] = true
result = append(result, path)
}
return paths
return result
}

View File

@ -37,7 +37,7 @@ func (s *Site) WatchFiles() (<-chan FilesEvent, error) {
)
go func() {
for {
paths := s.sitePaths(<-debounced)
paths := s.affectsBuildFilter(<-debounced)
if len(paths) > 0 {
// Create a new timestamp. Except under pathological
// circumstances, it will be close enough.