I have spent some time to figure out how to make HUGO_MODULE_REPLACEMENTS work, but have been unsuccessful. The replace command in go.mod works but I would like to avoid having to edit the go.mod each time I am tweaking my site’s theme. The HUGO_MODULE_REPLACEMENTS env var would fit the bill perfectly, but it doesn’t work for me.
Here is a recipe that reproduces the problem consistently for me. Can anyone else please verify and may be suggest what I could be doing wrong here.
mkdir -p /tmp/hugo_temp
cd /tmp/hugo_temp
# download the theme module
git clone https://gitlab.com/kaushalmodi/hugo-mwe-theme
# download the minimum working example site repo to a site/ directory
git clone --single-branch -b use-hugo-module-theme https://gitlab.com/hugo-mwe/hugo-mwe site
cd site
Inside the site directory, you will find a bash script srv.sh that uses HUGO_MODULE_REPLACEMENTS env var to replace the gitlab.com/kaushalmodi/hugo-mwe-theme module reference with a local path.
Testing replace in go.mod (works)
Uncomment the // replace gitlab.com/kaushalmodi/hugo-mwe-theme => ../hugo-mwe-theme line in site/go.mod and save that file.
@kaushalmodi When using the env var vs. replace in go.mod you need to remember that the env var operates relatives to the themes dir (even if you are not using a theme), so you need more ../. For a site you would need ../../hugo-mwe-theme and for a module with an exampleSite for which you are generating the exampleSite you would need ../../../hugo-mwe-theme.
I use it every day, so I’m sure it works, but I guess there are some caveats worth knowing:
Using HUGO_MODULE_REPLACEMENTS is the same as manually editing the path in your module config in config.toml – which is not the same as a replacement inside go.mod
I suspect your problem is a path confusion issue, as relative paths resolves relative to themeDir – I notice in one shell script I use for this purpose is that I use absolute paths on the right side of the fence, which I suspect is easier to reason about.
Go 1.18 (soon to be released) comes with a concept of workspaces (go.workspace files), which should make (cross fingers!) this situation much cleaner/better. That would be files that you would (normally) put in .gitignore.
ok, I got the path replacement working in the example repo above. But looks like it is still causing problems (even when using absolute path for replacement), if the replaced module depends on other modules.
For example, I have this theme module for my main site that depends on few other modules:
export HUGO_THEMESDIR="$(pwd)/../"
# The replacement paths need to be relative to Hugo's themesDir.
export HUGO_MODULE_REPLACEMENTS="gitlab.com/kaushalmodi/hugo-theme-refined -> hugo-theme-refined"
hugo mod graph
it looks like it found the main theme module in “themesDir”, but it failed to get one of the nested modules:
But /home/kmodi/hugo directory does contain hugo-search-fuse-js/ directory.
Short recipe to reproduce this issue
mkdir -p /tmp/hugo_temp_36746
cd /tmp/hugo_temp_36746
# download the theme module
git clone --single-branch -b add-nested-module https://gitlab.com/kaushalmodi/hugo-mwe-theme
# download the minimum working example site repo to a site/ directory
git clone --single-branch -b use-hugo-module-theme https://gitlab.com/hugo-mwe/hugo-mwe site
cd site
./srv.sh
@kaushalmodi I have observed this as well. I am not sure it is a bug per-se (or rather a lack of documentation).
There are a couple of ways to solve the issue. One is add the nested module(s) to the HUGO_MODULE_REPLACEMENTS. The other (IIRC) is to use hugo mod vendor and commit the _vendor directory in the top-level module.
I’m pretty sure what is happening is that when you use ‘replacements’ there isn’t the usual downloading of the module into the module cache directory, nor download of nested module (because the usual code path is not followed). This may be a Go module behavior rather than Hugo-specific.
I probably should have commented that this was happening in the forum, but I was busy and forgot.
Maybe @bep has some thoughts on whether this is something Hugo can handle better, or if it’s more a case of updating the docs.
set -euo pipefail # http://redsymbol.net/articles/unofficial-bash-strict-mode
IFS=$'\n\t'
port="${1:-3333}" # default
# shellcheck disable=SC2155
export HUGO_THEMESDIR="$(pwd)/../" # The replacement paths need to be relative to Hugo's themesDir.
replacements=("gitlab.com/kaushalmodi/hugo-theme-refined"
", github.com/kaushalmodi/hugo-search-fuse-js"
", github.com/kaushalmodi/hugo-jf2"
", github.com/kaushalmodi/hugo-atom-feed"
", github.com/kaushalmodi/hugo-debugprint")
HUGO_MODULE_REPLACEMENTS=""
for mod in "${replacements[@]}"
do
HUGO_MODULE_REPLACEMENTS="${HUGO_MODULE_REPLACEMENTS}${mod} -> $(basename "${mod}")"
done
export HUGO_MODULE_REPLACEMENTS
echo "Hugo Module Graph:"
hugo mod graph
hugo server \
--buildDrafts \
--buildFuture \
--navigateToChanged \
--port "${port}"
Alright… I am sticking with this for now; works robustly (for me at least) for theme modules with nested modules or not:
set -euo pipefail # http://redsymbol.net/articles/unofficial-bash-strict-mode
IFS=$'\n\t'
port="${1:-3333}" # default
mod_base_dir=".."
mods_to_be_replaced=("gitlab.com/kaushalmodi/hugo-theme-refined")
sed -i '/replace .* =>/d' go.mod
for mod in "${mods_to_be_replaced[@]}"
do
echo "replace ${mod} => ${mod_base_dir}/$(basename "${mod}")" >> go.mod
done
echo "Hugo Module Graph:"
hugo mod graph
hugo server \
--buildDrafts \
--buildFuture \
--navigateToChanged \
--port "${port}"