// Copyright 2019 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache 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://www.apache.org/licenses/LICENSE-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 modules
import (
"bufio"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"regexp"
"strings"
"time"
"github.com/bep/debounce"
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/loggers"
"github.com/spf13/cast"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/parser/metadecoders"
"github.com/gohugoio/hugo/hugofs/files"
"golang.org/x/mod/module"
"github.com/gohugoio/hugo/config"
"github.com/spf13/afero"
)
var ErrNotExist = errors.New("module does not exist")
const vendorModulesFilename = "modules.txt"
func (h *Client) Collect() (ModulesConfig, error) {
mc, coll := h.collect(true)
if coll.err != nil {
return mc, coll.err
}
if err := (&mc).setActiveMods(h.logger); err != nil {
return mc, err
}
if h.ccfg.HookBeforeFinalize != nil {
if err := h.ccfg.HookBeforeFinalize(&mc); err != nil {
return mc, err
}
}
if err := (&mc).finalize(h.logger); err != nil {
return mc, err
}
return mc, nil
}
func (h *Client) collect(tidy bool) (ModulesConfig, *collector) {
if h == nil {
panic("nil client")
}
c := &collector{
Client: h,
}
c.collect()
if c.err != nil {
return ModulesConfig{}, c
}
// https://github.com/gohugoio/hugo/issues/6115
/*if !c.skipTidy && tidy {
if err := h.tidy(c.modules, true); err != nil {
c.err = err
return ModulesConfig{}, c
}
}*/
var workspaceFilename string
if h.ccfg.ModuleConfig.Workspace != WorkspaceDisabled {
workspaceFilename = h.ccfg.ModuleConfig.Workspace
}
return ModulesConfig{
AllModules: c.modules,
GoModulesFilename: c.GoModulesFilename,
GoWorkspaceFilename: workspaceFilename,
}, c
}
type ModulesConfig struct {
// All active modules.
AllModules Modules
// Set if this is a Go modules enabled project.
GoModulesFilename string
// Set if a Go workspace file is configured.
GoWorkspaceFilename string
}
func (m ModulesConfig) HasConfigFile() bool {
for _, mod := range m.AllModules {
if len(mod.ConfigFilenames()) > 0 {
return true
}
}
return false
}
func (m *ModulesConfig) setActiveMods(logger loggers.Logger) error {
for _, mod := range m.AllModules {
if !mod.Config().HugoVersion.IsValid() {
logger.Warnf(`Module %q is not compatible with this Hugo version: %s; run "hugo mod graph" for more information.`, mod.Path(), mod.Config().HugoVersion)
}
}
return nil
}
func (m *ModulesConfig) finalize(logger loggers.Logger) error {
for _, mod := range m.AllModules {
m := mod.(*moduleAdapter)
m.mounts = filterUnwantedMounts(m.mounts)
}
return nil
}
func filterUnwantedMounts(mounts []Mount) []Mount {
// Remove duplicates
seen := make(map[string]bool)
tmp := mounts[:0]
for _, m := range mounts {
if !seen[<