1// Copyright 2019 The Hugo Authors. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14// Package modules provides a client that can be used to manage Hugo Components, 15// what's referred to as Hugo Modules. Hugo Modules is built on top of Go Modules, 16// but also supports vendoring and components stored directly in the themes dir. 17package modules 18 19import ( 20 "time" 21 22 "github.com/gohugoio/hugo/config" 23) 24 25var _ Module = (*moduleAdapter)(nil) 26 27type Module interface { 28 29 // Optional config read from the configFilename above. 30 Cfg() config.Provider 31 32 // The decoded module config and mounts. 33 Config() Config 34 35 // Optional configuration filenames (e.g. "/themes/mytheme/config.json"). 36 // This will be added to the special configuration watch list when in 37 // server mode. 38 ConfigFilenames() []string 39 40 // Directory holding files for this module. 41 Dir() string 42 43 // This module is disabled. 44 Disabled() bool 45 46 // Returns whether this is a Go Module. 47 IsGoMod() bool 48 49 // Any directory remappings. 50 Mounts() []Mount 51 52 // In the dependency tree, this is the first module that defines this module 53 // as a dependency. 54 Owner() Module 55 56 // Returns the path to this module. 57 // This will either be the module path, e.g. "github.com/gohugoio/myshortcodes", 58 // or the path below your /theme folder, e.g. "mytheme". 59 Path() string 60 61 // Replaced by this module. 62 Replace() Module 63 64 // Returns whether Dir points below the _vendor dir. 65 Vendor() bool 66 67 // The module version. 68 Version() string 69 70 // Time version was created. 71 Time() time.Time 72 73 // Whether this module's dir is a watch candidate. 74 Watch() bool 75} 76 77type Modules []Module 78 79type moduleAdapter struct { 80 path string 81 dir string 82 version string 83 vendor bool 84 disabled bool 85 projectMod bool 86 owner Module 87 88 mounts []Mount 89 90 configFilenames []string 91 cfg config.Provider 92 config Config 93 94 // Set if a Go module. 95 gomod *goModule 96} 97 98func (m *moduleAdapter) Cfg() config.Provider { 99 return m.cfg 100} 101 102func (m *moduleAdapter) Config() Config { 103 return m.config 104} 105 106func (m *moduleAdapter) ConfigFilenames() []string { 107 return m.configFilenames 108} 109 110func (m *moduleAdapter) Dir() string { 111 // This may point to the _vendor dir. 112 if !m.IsGoMod() || m.dir != "" { 113 return m.dir 114 } 115 return m.gomod.Dir 116} 117 118func (m *moduleAdapter) Disabled() bool { 119 return m.disabled 120} 121 122func (m *moduleAdapter) IsGoMod() bool { 123 return m.gomod != nil 124} 125 126func (m *moduleAdapter) Mounts() []Mount { 127 return m.mounts 128} 129 130func (m *moduleAdapter) Owner() Module { 131 return m.owner 132} 133 134func (m *moduleAdapter) Path() string { 135 if !m.IsGoMod() || m.path != "" { 136 return m.path 137 } 138 return m.gomod.Path 139} 140 141func (m *moduleAdapter) Replace() Module { 142 if m.IsGoMod() && !m.Vendor() && m.gomod.Replace != nil { 143 return &moduleAdapter{ 144 gomod: m.gomod.Replace, 145 owner: m.owner, 146 } 147 } 148 return nil 149} 150 151func (m *moduleAdapter) Vendor() bool { 152 return m.vendor 153} 154 155func (m *moduleAdapter) Version() string { 156 if !m.IsGoMod() || m.version != "" { 157 return m.version 158 } 159 return m.gomod.Version 160} 161 162func (m *moduleAdapter) Time() time.Time { 163 if !m.IsGoMod() || m.gomod.Time == nil { 164 return time.Time{} 165 } 166 167 return *m.gomod.Time 168 169} 170 171func (m *moduleAdapter) Watch() bool { 172 if m.Owner() == nil { 173 // Main project 174 return true 175 } 176 177 if !m.IsGoMod() { 178 // Module inside /themes 179 return true 180 } 181 182 if m.Replace() != nil { 183 // Version is not set when replaced by a local folder. 184 return m.Replace().Version() == "" 185 } 186 187 return false 188} 189