golist

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

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

View Source
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

View Source
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.

func (*ExitError) Error

func (e *ExitError) Error() string

Error returns a one-line summary suitable for logging.

func (*ExitError) Is

func (e *ExitError) Is(target error) bool

Is reports whether target is ErrGoListFailed; this is what makes errors.Is(err, ErrGoListFailed) true when err is an *ExitError.

func (*ExitError) Unwrap

func (e *ExitError) Unwrap() error

Unwrap returns the wrapped *exec.ExitError when one is captured, else nil. Callers can use errors.As to extract the *exec.ExitError for low-level inspection (e.g. signal info on Unix).

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

func WithDir(dir string) Option

WithDir sets the working directory for the spawned `go list` process. Defaults to the caller's current working directory.

func WithEnv

func WithEnv(env []string) Option

WithEnv overrides the environment for the spawned `go list` process. Defaults to os.Environ() (i.e. inheriting the parent process env). Useful for hermetic test setups.

func WithGoBin

func WithGoBin(bin string) Option

WithGoBin overrides the `go` binary path. Defaults to "go" (resolved via $PATH). Useful for testing against non-default toolchains.

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

func Run(ctx context.Context, tags []string, patterns []string, opts ...Option) ([]Package, error)

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.

Jump to

Keyboard shortcuts

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