Documentation
¶
Overview ¶
Package golist is a thin io shell around `go list -deps -json`. It exposes typed Package values parsed from `go list`'s JSON output, without going through golang.org/x/tools/go/packages.
This package is the only part of cascade that shells out to `go`.
API stability: pre-v1.0, package surface may change. See repo README.
Index ¶
Constants ¶
const ParseErrorMaxPayload = 4096
ParseErrorMaxPayload is the maximum number of bytes captured in ParseError.Payload. Larger payloads are truncated; the truncation is not separately marked because the offset + cause already convey the failure point.
Variables ¶
var ( // ErrGoNotFound is returned when the `go` binary cannot be found on // $PATH (or at the path configured via WithGoBin). The wrapped error // is exec.ErrNotFound. ErrGoNotFound = errors.New("go binary not found") // ErrGoListFailed is returned when `go list` exits with a non-zero // status. Use errors.As(err, &e) with a *ExitError to extract the // stderr capture and full argv. ErrGoListFailed = errors.New("go list failed") // ErrParseFailed is returned when streaming JSON decoding of `go list` // output fails partway through. Use errors.As(err, &e) with a // *ParseError to extract the byte offset and offending payload. ErrParseFailed = errors.New("go list output parse failed") )
Sentinel errors for category matching via errors.Is. The typed errors below (*ExitError, *ParseError) implement Is to match the corresponding sentinel; callers should match against the sentinel for category and use errors.As to extract the typed error for diagnostic context.
These follow the EH-36 sentinel naming convention (ErrXxx) and are the only mechanism callers should use to classify errors — string-match against Error() output is forbidden (AP-13).
Functions ¶
This section is empty.
Types ¶
type ExitError ¶
type ExitError struct {
// Cmd is the full argv as passed to exec, in order, for reproduction.
Cmd []string
// Dir is the working directory the command was run in (absolute path
// when the configured WithDir was absolute; otherwise as configured).
Dir string
// ExitCode is the subprocess exit code (typically 1 for `go list`
// errors; may be other values).
ExitCode int
// Stderr is the captured stderr output, verbatim and untruncated.
// `go list`'s stderr on real failures (e.g. "go: updates to go.mod
// needed") is small and the diagnostic value is high.
Stderr string
// contains filtered or unexported fields
}
ExitError captures the diagnostic context when `go list` exits with a non-zero status. errors.Is(err, ErrGoListFailed) returns true; the wrapped *exec.ExitError (when applicable) is reachable via errors.As or by calling Unwrap directly.
type Module ¶
type Module struct {
// Path is the module path, e.g. "github.com/geomyidia/cascade".
Path string `json:"Path"`
// Main is true when this is the main module being built (the one
// the working directory belongs to), false for dependencies.
Main bool `json:"Main,omitempty"`
}
Module identifies which Go module a Package belongs to. Nil on Package when the package is from the standard library.
type Option ¶
type Option func(*runConfig)
Option configures a Run call. Apply options after the required positional args. See WithDir, WithEnv, WithGoBin.
func WithDir ¶
WithDir sets the working directory for the spawned `go list` process. Defaults to the caller's current working directory.
type Package ¶
type Package struct {
// Identity
ImportPath string `json:"ImportPath"`
Dir string `json:"Dir"`
// Source files in this package, by category
GoFiles []string `json:"GoFiles,omitempty"`
TestGoFiles []string `json:"TestGoFiles,omitempty"`
XTestGoFiles []string `json:"XTestGoFiles,omitempty"`
IgnoredGoFiles []string `json:"IgnoredGoFiles,omitempty"`
// Direct imports, by source category
Imports []string `json:"Imports,omitempty"`
TestImports []string `json:"TestImports,omitempty"`
XTestImports []string `json:"XTestImports,omitempty"`
// Categorisation (used downstream to filter stdlib / external deps)
Standard bool `json:"Standard,omitempty"`
Module *Module `json:"Module,omitempty"`
}
Package mirrors the subset of `go list -deps -json` output that cascade's downstream packages (depgraph, changeset) consume. Fields not consumed are deliberately omitted — adding a field is a decision driven by a downstream need, not a default passthrough.
All path fields are absolute (as `go list` reports them). All slice fields are nil-safe (a package with no test imports has TestImports == nil, not []string{}; callers should not distinguish).
func Run ¶
Run shells out to `go list -deps -json -tags=<tags> <patterns...>` in the configured working directory, parses the streaming JSON output, and returns the parsed packages in encounter order (alphabetical by import path within each module — `go list`'s own order).
Behaviour on error:
- If `go` is not on PATH (or at WithGoBin's path): returns an error wrapping ErrGoNotFound. errors.Is(err, ErrGoNotFound) is true.
- If `go list` exits non-zero: returns a *ExitError with stderr captured. errors.Is(err, ErrGoListFailed) is true; errors.As(&e) extracts the *ExitError.
- If JSON parsing fails: returns a *ParseError with the offending payload. errors.Is(err, ErrParseFailed) is true; errors.As(&e) extracts the *ParseError.
- If ctx is cancelled or its deadline expires: the spawned `go list` process is killed (via exec.CommandContext); the returned error wraps ctx.Err() so errors.Is(err, context.Canceled) / errors.Is(err, context.DeadlineExceeded) match.
Concurrency: Run may be called concurrently from multiple goroutines. Each call spawns its own subprocess. The returned []Package is safe for concurrent reads after Run returns; callers must not mutate it.
Defaults applied to inputs:
- patterns: nil or empty → []string{"./..."} (the common case).
- tags: nil or empty → the -tags flag is omitted entirely from the argv (not passed as -tags="").
type ParseError ¶
type ParseError struct {
// Offset is the byte offset in the streaming input where decoding
// stopped. Useful for correlating with the captured Payload.
Offset int64
// Payload is the offending payload, truncated to ParseErrorMaxPayload
// bytes. Captures bytes the decoder had buffered plus any remaining
// readable input at the failure point.
Payload string
// Cause is the underlying json error (typically *json.SyntaxError or
// io.ErrUnexpectedEOF for truncated input).
Cause error
}
ParseError captures the diagnostic context when JSON decoding of `go list` output fails. errors.Is(err, ErrParseFailed) returns true; the wrapped json error is reachable via errors.As(err, &e).Cause or errors.Unwrap.
func (*ParseError) Error ¶
func (e *ParseError) Error() string
Error returns a one-line summary suitable for logging.
func (*ParseError) Is ¶
func (e *ParseError) Is(target error) bool
Is reports whether target is ErrParseFailed.
func (*ParseError) Unwrap ¶
func (e *ParseError) Unwrap() error
Unwrap returns the underlying json error so errors.Is/errors.As can reach json.SyntaxError, io.ErrUnexpectedEOF, etc.