Skip to content

Commit

Permalink
Move the mount duplicate filter to the modules package
Browse files Browse the repository at this point in the history
Also simplify the mount validation logic. There are plenty of ways a user can create mount configs that behaves oddly.
  • Loading branch information
bep committed Jul 31, 2019
1 parent edf9f0a commit 4b6c5eb
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 121 deletions.
80 changes: 48 additions & 32 deletions hugolib/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,17 +207,25 @@ func LoadConfig(d ConfigSourceDescriptor, doWithConfig ...func(cfg config.Provid
return v, configFiles, err
}

mods, modulesConfigFiles, err := l.collectModules(modulesConfig, v)
if err != nil {
return v, configFiles, err
}
// Need to run these after the modules are loaded, but before
// they are finalized.
collectHook := func(m *modules.ModulesConfig) error {
if err := loadLanguageSettings(v, nil); err != nil {
return err
}

if err := loadLanguageSettings(v, nil); err != nil {
return v, configFiles, err
mods := m.ActiveModules

// Apply default project mounts.
if err := modules.ApplyProjectConfigDefaults(v, mods[len(mods)-1]); err != nil {
return err
}

return nil
}

// Apply default project mounts.
if err := modules.ApplyProjectConfigDefaults(v, mods[len(mods)-1]); err != nil {
_, modulesConfigFiles, err := l.collectModules(modulesConfig, v, collectHook)
if err != nil {
return v, configFiles, err
}

Expand Down Expand Up @@ -406,7 +414,7 @@ func (l configLoader) loadModulesConfig(v1 *viper.Viper) (modules.Config, error)
return modConfig, nil
}

func (l configLoader) collectModules(modConfig modules.Config, v1 *viper.Viper) (modules.Modules, []string, error) {
func (l configLoader) collectModules(modConfig modules.Config, v1 *viper.Viper, hookBeforeFinalize func(m *modules.ModulesConfig) error) (modules.Modules, []string, error) {
workingDir := l.WorkingDir
if workingDir == "" {
workingDir = v1.GetString("workingDir")
Expand All @@ -420,16 +428,40 @@ func (l configLoader) collectModules(modConfig modules.Config, v1 *viper.Viper)
if err != nil {
return nil, nil, err
}

v1.Set("filecacheConfigs", filecacheConfigs)

var configFilenames []string

hook := func(m *modules.ModulesConfig) error {
for _, tc := range m.ActiveModules {
if tc.ConfigFilename() != "" {
if tc.Watch() {
configFilenames = append(configFilenames, tc.ConfigFilename())
}
if err := l.applyThemeConfig(v1, tc); err != nil {
return err
}
}
}

if hookBeforeFinalize != nil {
return hookBeforeFinalize(m)
}

return nil

}

modulesClient := modules.NewClient(modules.ClientConfig{
Fs: l.Fs,
Logger: l.Logger,
WorkingDir: workingDir,
ThemesDir: themesDir,
CacheDir: filecacheConfigs.CacheDirModules(),
ModuleConfig: modConfig,
IgnoreVendor: ignoreVendor,
Fs: l.Fs,
Logger: l.Logger,
HookBeforeFinalize: hook,
WorkingDir: workingDir,
ThemesDir: themesDir,
CacheDir: filecacheConfigs.CacheDirModules(),
ModuleConfig: modConfig,
IgnoreVendor: ignoreVendor,
})

v1.Set("modulesClient", modulesClient)
Expand All @@ -442,22 +474,6 @@ func (l configLoader) collectModules(modConfig modules.Config, v1 *viper.Viper)
// Avoid recreating these later.
v1.Set("allModules", moduleConfig.ActiveModules)

if len(moduleConfig.ActiveModules) == 0 {
return nil, nil, nil
}

var configFilenames []string
for _, tc := range moduleConfig.ActiveModules {
if tc.ConfigFilename() != "" {
if tc.Watch() {
configFilenames = append(configFilenames, tc.ConfigFilename())
}
if err := l.applyThemeConfig(v1, tc); err != nil {
return nil, nil, err
}
}
}

if moduleConfig.GoModulesFilename != "" {
// We want to watch this for changes and trigger rebuild on version
// changes etc.
Expand Down
42 changes: 4 additions & 38 deletions hugolib/filesystems/basefs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package filesystems
import (
"io"
"os"
"path"
"path/filepath"
"strings"
"sync"
Expand Down Expand Up @@ -454,7 +453,6 @@ func (b *sourceFilesystemsBuilder) createMainOverlayFs(p *paths.Paths) (*filesys
// The theme components are ordered from left to right.
// We need to revert it to get the
// overlay logic below working as expected, with the project on top (last).

for i, mod := range mods {
dir := mod.Dir()

Expand All @@ -463,11 +461,9 @@ func (b *sourceFilesystemsBuilder) createMainOverlayFs(p *paths.Paths) (*filesys
}

isMainProject := mod.Owner() == nil
// TODO(bep) embed mount + move any duplicate/overlap
modsReversed[i] = mountsDescriptor{
mounts: mod.Mounts(),
Module: mod,
dir: dir,
watch: mod.Watch(),
isMainProject: isMainProject,
}
}
Expand Down Expand Up @@ -500,36 +496,7 @@ func (b *sourceFilesystemsBuilder) createModFs(
return paths.AbsPathify(md.dir, path)
}

seen := make(map[string]bool)

var mounts []modules.Mount

OUTER:
for i, mount := range md.mounts {
key := path.Join(mount.Lang, mount.Source, mount.Target)
if seen[key] {
continue
}
seen[key] = true

// Prevent overlapping mounts
for j, mount2 := range md.mounts {
if j == i || mount2.Target != mount.Target {
continue
}
source := mount.Source
if !strings.HasSuffix(source, filePathSeparator) {
source += filePathSeparator
}
if strings.HasPrefix(mount2.Source, source) {
continue OUTER
}
}

mounts = append(mounts, mount)
}

for _, mount := range mounts {
for _, mount := range md.Mounts() {

mountWeight := 1
if md.isMainProject {
Expand All @@ -540,7 +507,7 @@ OUTER:
From: mount.Target,
To: absPathify(mount.Source),
Meta: hugofs.FileMeta{
"watch": md.watch,
"watch": md.Watch(),
"mountWeight": mountWeight,
},
}
Expand Down Expand Up @@ -703,9 +670,8 @@ func (c *filesystemsCollector) reverseFis(fis []hugofs.FileMetaInfo) {
}

type mountsDescriptor struct {
mounts []modules.Mount
modules.Module
dir string
watch bool // whether this is a candidate for watching in server mode.
isMainProject bool
}

Expand Down
43 changes: 22 additions & 21 deletions modules/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ const (
// level imports to start out.
func NewClient(cfg ClientConfig) *Client {
fs := cfg.Fs

n := filepath.Join(cfg.WorkingDir, goModFilename)
goModEnabled, _ := afero.Exists(fs, n)
var goModFilename string
Expand Down Expand Up @@ -97,9 +96,7 @@ func NewClient(cfg ClientConfig) *Client {

return &Client{
fs: fs,
ignoreVendor: cfg.IgnoreVendor,
workingDir: cfg.WorkingDir,
themesDir: cfg.ThemesDir,
ccfg: cfg,
logger: logger,
moduleConfig: mcfg,
environ: env,
Expand All @@ -111,14 +108,7 @@ type Client struct {
fs afero.Fs
logger *loggers.Logger

// Ignore any _vendor directory.
ignoreVendor bool

// Absolute path to the project dir.
workingDir string

// Absolute path to the project's themes dir.
themesDir string
ccfg ClientConfig

// The top level module config
moduleConfig Config
Expand Down Expand Up @@ -194,7 +184,7 @@ func (c *Client) Tidy() error {
// meaning that if the top-level module is vendored, that will be the full
// set of dependencies.
func (c *Client) Vendor() error {
vendorDir := filepath.Join(c.workingDir, vendord)
vendorDir := filepath.Join(c.ccfg.WorkingDir, vendord)
if err := c.rmVendorDir(vendorDir); err != nil {
return err
}
Expand Down Expand Up @@ -284,7 +274,7 @@ func (c *Client) Init(path string) error {
return errors.Wrap(err, "failed to init modules")
}

c.GoModulesFilename = filepath.Join(c.workingDir, goModFilename)
c.GoModulesFilename = filepath.Join(c.ccfg.WorkingDir, goModFilename)

return nil
}
Expand Down Expand Up @@ -335,7 +325,7 @@ func (c *Client) rewriteGoMod(name string, isGoMod map[string]bool) error {
return err
}
if data != nil {
if err := afero.WriteFile(c.fs, filepath.Join(c.workingDir, name), data, 0666); err != nil {
if err := afero.WriteFile(c.fs, filepath.Join(c.ccfg.WorkingDir, name), data, 0666); err != nil {
return err
}
}
Expand All @@ -352,7 +342,7 @@ func (c *Client) rewriteGoModRewrite(name string, isGoMod map[string]bool) ([]by
modlineSplitter := getModlineSplitter(name == goModFilename)

b := &bytes.Buffer{}
f, err := c.fs.Open(filepath.Join(c.workingDir, name))
f, err := c.fs.Open(filepath.Join(c.ccfg.WorkingDir, name))
if err != nil {
if os.IsNotExist(err) {
// It's been deleted.
Expand Down Expand Up @@ -424,7 +414,7 @@ func (c *Client) runGo(
cmd := exec.CommandContext(ctx, "go", args...)

cmd.Env = c.environ
cmd.Dir = c.workingDir
cmd.Dir = c.ccfg.WorkingDir
cmd.Stdout = stdout
cmd.Stderr = io.MultiWriter(stderr, os.Stderr)

Expand Down Expand Up @@ -482,11 +472,22 @@ func (c *Client) tidy(mods Modules, goModOnly bool) error {

// ClientConfig configures the module Client.
type ClientConfig struct {
Fs afero.Fs
Logger *loggers.Logger
Fs afero.Fs
Logger *loggers.Logger

// If set, it will be run before we do any duplicate checks for modules
// etc.
HookBeforeFinalize func(m *ModulesConfig) error

// Ignore any _vendor directory.
IgnoreVendor bool
WorkingDir string
ThemesDir string // Absolute directory path

// Absolute path to the project dir.
WorkingDir string

// Absolute path to the project's themes dir.
ThemesDir string

CacheDir string // Module cache
ModuleConfig Config
}
Expand Down
Loading

0 comments on commit 4b6c5eb

Please sign in to comment.