Help us shape the future of Go! Take the 2026 Go Developer Survey

strategy

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package strategy is the tool-isolation strategy: which files hold a tool's go.mod and go.sum, and which strategies a tools directory already uses.

A Strategy says how tools are kept apart. A Layout pairs a strategy with a tools directory and answers where each tool's files live. Detect reads a directory on disk and reports which layouts it holds.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ValidateName

func ValidateName(name string) error

ValidateName rejects tool names that would escape the tools directory or break file handling: empty, "." and "..", a leading "-", a path separator, whitespace and control characters.

Types

type Detection

type Detection struct {
	// Strategy is the dominant layout ("" when the directory is absent or
	// holds no recognizable layout). Priority: unified, module, split.
	Strategy Strategy
	// Found lists every layout present, in priority order.
	Found []Strategy
}

Detection is what Detect found in a tools directory.

func Detect

func Detect(dir string) Detection

Detect inspects dir, an on-disk path, and reports which layouts it holds. Dot-entries are ignored and symlinks are followed: detection is read-only.

Example

Detect reports every layout a directory holds; more than one is a hybrid directory with a warning to show.

package main

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/piusalfred/gotools/internal/strategy"
)

func main() {
	dir, _ := os.MkdirTemp("", "strategy-example")
	defer os.RemoveAll(dir)

	_ = os.WriteFile(filepath.Join(dir, "gofumpt.mod"), []byte("module x\n"), 0o600)
	_ = os.MkdirAll(filepath.Join(dir, "gci"), 0o755)
	_ = os.WriteFile(filepath.Join(dir, "gci", "go.mod"), []byte("module y\n"), 0o600)

	d := strategy.Detect(dir)

	fmt.Println(d.Strategy, d.Found, d.Hybrid())
	fmt.Println(d.Warning("tools", "gotools"))

}
Output:
module [module split] true
⚠️  Hybrid tools directory detected in tools/:
   - module   (subdirectories with go.mod)
   - split    (flat .mod files)
   Run 'gotools migrate <strategy>' to clean up.

func (Detection) Hybrid

func (d Detection) Hybrid() bool

Hybrid reports whether more than one layout is present.

func (Detection) Warning

func (d Detection) Warning(dir, program string) string

Warning returns the hybrid-directory warning, without a trailing newline, or "" when the directory is not hybrid. dir is the display path and program the command name the warning points at.

type Layout

type Layout struct {
	Strategy Strategy
	Dir      string // the tools directory, relative to the project root
}

Layout is a strategy applied to a tools directory.

Example

A Layout answers where a tool's files live under each strategy.

package main

import (
	"fmt"

	"github.com/piusalfred/gotools/internal/strategy"
)

func main() {
	for _, s := range []strategy.Strategy{strategy.Unified, strategy.Split, strategy.Module} {
		mod, _ := strategy.Layout{Strategy: s, Dir: "./tools/"}.ModFileRel("gofumpt")
		fmt.Printf("%-8s %s\n", s, mod)
	}

	// A name that would escape the tools directory is refused.
	_, err := strategy.Layout{Strategy: strategy.Split, Dir: "tools"}.ModFileRel("../x")
	fmt.Println(err)

}
Output:
unified  tools/go.mod
split    tools/gofumpt.mod
module   tools/gofumpt/go.mod
invalid tool name (must not contain a path separator): ../x

func (Layout) ModFile

func (l Layout) ModFile(root, name string) (string, error)

ModFile is ModFileRel as a path under root.

func (Layout) ModFileRel

func (l Layout) ModFileRel(name string) (string, error)

ModFileRel is the modfile holding tool name, relative to the project root and slash-separated:

unified  <dir>/go.mod
split    <dir>/<name>.mod
module   <dir>/<name>/go.mod

A name that is joined into the path is validated.

func (Layout) ModulePath

func (l Layout) ModulePath(prefix, name string) string

ModulePath is the module path for a tool's own go.mod (name != "") or for the tools directory itself (name == ""), under prefix. The directory is cleaned, so "./tools" and "tools/" give the same path.

func (Layout) SumFile

func (l Layout) SumFile(root, name string) (string, error)

SumFile is SumFileRel as a path under root.

func (Layout) SumFileRel

func (l Layout) SumFileRel(name string) (string, error)

SumFileRel is the checksum file matching ModFileRel.

func (Layout) ToolsDir

func (l Layout) ToolsDir(root string) string

ToolsDir is the tools directory under root.

type Strategy

type Strategy string

Strategy is a tool-isolation strategy.

const (
	// Split keeps one <name>.mod and <name>.sum per tool in a flat directory.
	Split Strategy = "split"
	// Module keeps one <name>/go.mod per tool.
	Module Strategy = "module"
	// Unified keeps every tool directive in one go.mod.
	Unified Strategy = "unified"
)

func Parse

func Parse(s string) (Strategy, error)

Parse returns the strategy named s, or an Environment error when it is not one of the three.

func (Strategy) Valid

func (s Strategy) Valid() bool

Valid reports whether s is one of the three known strategies.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL