Skip to content

Instantly share code, notes, and snippets.

@ardnew
Created October 29, 2022 09:23
Show Gist options
  • Save ardnew/f1389c545026d3064e247e541770b7e8 to your computer and use it in GitHub Desktop.
Save ardnew/f1389c545026d3064e247e541770b7e8 to your computer and use it in GitHub Desktop.
Shell script to add go.mod replace directives when working with multiple local modules
#!/bin/bash
usage() {
cat <<__usage__
-- DESCRIPTION -----------------------------------------------------------------
Insert a 'replace' directive into each given Go module (default: PWD) that
defines a local file path of a Go package to import instead of the published
package named in any of the given modules' import lists.
-- SYNOPSIS --------------------------------------------------------------------
${0##*/} IMPORT PATH [MODULE ...]
-- ARGUMENTS -------------------------------------------------------------------
- IMPORT Package path used in Go import clauses
- PATH Local filepath to use for the imported package
- MODULE (optional) Local filepath of Go module to modify
default: $PWD
__usage__
exit
}
# halt prints an error message to stderr and exits the script with the given
# status code. The error message is provided as a printf-style format string
# and associated parameters.
# % halt [STATUS [FORMAT [PARAM...]]]
halt() {
local ret=${1:-127}
local pre='error' msg=${2:-'(unspecified)'}
[[ $ret =~ ^[0-9]*$ ]] ||
ret=126
[[ $# -gt 0 && $1 -eq 0 ]] &&
pre='exit' msg=${2:-'OK'}
[[ $# -ge 3 ]] &&
msg=$( printf -- "${2}" "${@:3}" )
printf -- '%s(%d): %s\n' "${pre}" ${ret} "${msg}" >&2
exit ${ret}
}
relpath() {
[ $# -ge 2 ] &&
perl -MFile::Spec::Functions=abs2rel -le \
'print abs2rel(@ARGV)' "${2}" "${1}"
}
replace() {
[ $# -ge 2 ] || return 1
go mod edit -replace "${1}=${2}"
go mod tidy
}
[ $# -ge 2 ] || usage
module=( "${@:3}" )
[ ${#module[@]} -gt 0 ] || module=( "$PWD" )
for mod in "${module[@]}"; do
[ -d "$mod" ] && mod="$mod/go.mod"
[ "${mod##*/}" = "go.mod" ] && [ -f "$mod" ] ||
halt 100 "module file invalid or not found: %s" "$mod"
path=${mod%/go.mod}
pushd "$path" &>/dev/null ||
halt 101 "failed to open directory: %s" "$path"
replace "$1" "$( relpath "${PWD}" "$2" )" ||
halt 102 "command failed: %s" "go mod edit / tidy"
popd &>/dev/null
done
@ardnew
Copy link
Author

ardnew commented Oct 29, 2022

I can never remember the syntax used in the go.mod file, and I recently found a need to update multiple modules at once.

TODO

  • Add a flag to remove the directive from a given list of modules

@ardnew
Copy link
Author

ardnew commented Apr 14, 2024

Warning

This script should no longer be used.

Tip

Go 1.18 added support for multi-module workspaces. You should now use a replace directive in go.work to replace paths in multiple modules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment