[![Go Reference](https://pkg.go.dev/badge/filippo.io/age.svg)](https://pkg.go.dev/filippo.io/age)
[![man page]()](https://filippo.io/age/age.1)
@@ -23,7 +29,9 @@ $ age --decrypt -i key.txt data.tar.gz.age > data.tar.gz
🔑 Hardware PIV tokens such as YubiKeys are supported through the [age-plugin-yubikey](https://github.com/str4d/age-plugin-yubikey) plugin.
-💬 The author pronounces it `[aɡe̞]`, like the Italian [“aghe”](https://translate.google.com/?sl=it&text=aghe).
+✨ For more plugins, implementations, tools, and integrations, check out the [awesome age](https://github.com/FiloSottile/awesome-age) list.
+
+💬 The author pronounces it `[aɡe̞]` [with a hard *g*](https://translate.google.com/?sl=it&text=aghe), like GIF, and is always spelled lowercase.
## Installation
@@ -53,7 +61,13 @@ $ age --decrypt -i key.txt data.tar.gz.age > data.tar.gz
-
Debian 11+ (Bullseye)
+
Debian 12+ (Bookworm)
+
+ apt install age
+
+
+
+
Debian 11 (Bullseye)
apt install age/bullseye-backports
(enable backports for age v1.0.0+)
@@ -116,7 +130,13 @@ $ age --decrypt -i key.txt data.tar.gz.age > data.tar.gz
Scoop (Windows)
- scoop bucket add extras; scoop install age
+ scoop bucket add extras && scoop install age
+
+
+
+
pkgx
+
+ pkgx install age
@@ -125,7 +145,7 @@ On Windows, Linux, macOS, and FreeBSD you can use the pre-built binaries.
```
https://dl.filippo.io/age/latest?for=linux/amd64
-https://dl.filippo.io/age/v1.0.0-rc.1?for=darwin/arm64
+https://dl.filippo.io/age/v1.1.1?for=darwin/arm64
...
```
@@ -137,6 +157,39 @@ go install filippo.io/age/cmd/...@latest
Help from new packagers is very welcome.
+### Verifying the release signatures
+
+If you download the pre-built binaries, you can check their
+[Sigsum](https://www.sigsum.org) proofs, which are like signatures with extra
+transparency: you can cryptographically verify that every proof is logged in a
+public append-only log, so you can hold the age project accountable for every
+binary release we ever produced. This is similar to what the [Go Checksum
+Database](https://go.dev/blog/module-mirror-launch) provides.
+
+```
+cat << EOF > age-sigsum-key.pub
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM1WpnEswJLPzvXJDiswowy48U+G+G1kmgwUE2eaRHZG
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAz2WM5CyPLqiNjk7CLl4roDXwKhQ0QExXLebukZEZFS
+EOF
+cat << EOF > sigsum-trust-policy.txt
+log 154f49976b59ff09a123675f58cb3e346e0455753c3c3b15d465dcb4f6512b0b https://poc.sigsum.org/jellyfish
+witness poc.sigsum.org/nisse 1c25f8a44c635457e2e391d1efbca7d4c2951a0aef06225a881e46b98962ac6c
+witness rgdd.se/poc-witness 28c92a5a3a054d317c86fc2eeb6a7ab2054d6217100d0be67ded5b74323c5806
+group demo-quorum-rule all poc.sigsum.org/nisse rgdd.se/poc-witness
+quorum demo-quorum-rule
+EOF
+
+curl -JLO "https://dl.filippo.io/age/v1.2.0?for=darwin/arm64"
+curl -JLO "https://dl.filippo.io/age/v1.2.0?for=darwin/arm64&proof"
+
+go install sigsum.org/sigsum-go/cmd/sigsum-verify@v0.8.0
+sigsum-verify -k age-sigsum-key.pub -p sigsum-trust-policy.txt \
+ age-v1.2.0-darwin-arm64.tar.gz.proof < age-v1.2.0-darwin-arm64.tar.gz
+```
+
+You can learn more about what's happening above in the [Sigsum
+docs](https://www.sigsum.org/getting-started/).
+
## Usage
For the full documentation, read [the age(1) man page](https://filippo.io/age/age.1).
diff --git a/vendor/filippo.io/age/age.go b/vendor/filippo.io/age/age.go
index a0ef0bb776..c9b17bc829 100644
--- a/vendor/filippo.io/age/age.go
+++ b/vendor/filippo.io/age/age.go
@@ -13,7 +13,7 @@
// age encrypted files are binary and not malleable. For encoding them as text,
// use the filippo.io/age/armor package.
//
-// Key management
+// # Key management
//
// age does not have a global keyring. Instead, since age keys are small,
// textual, and cheap, you are encouraged to generate dedicated keys for each
@@ -34,7 +34,7 @@
// infrastructure, you might want to consider implementing your own Recipient
// and Identity.
//
-// Backwards compatibility
+// # Backwards compatibility
//
// Files encrypted with a stable version (not alpha, beta, or release candidate)
// of age, or with any v1.0.0 beta or release candidate, will decrypt with any
@@ -51,6 +51,7 @@ import (
"errors"
"fmt"
"io"
+ "sort"
"filippo.io/age/internal/format"
"filippo.io/age/internal/stream"
@@ -84,6 +85,21 @@ type Recipient interface {
Wrap(fileKey []byte) ([]*Stanza, error)
}
+// RecipientWithLabels can be optionally implemented by a Recipient, in which
+// case Encrypt will use WrapWithLabels instead of Wrap.
+//
+// Encrypt will succeed only if the labels returned by all the recipients
+// (assuming the empty set for those that don't implement RecipientWithLabels)
+// are the same.
+//
+// This can be used to ensure a recipient is only used with other recipients
+// with equivalent properties (for example by setting a "postquantum" label) or
+// to ensure a recipient is always used alone (by returning a random label, for
+// example to preserve its authentication properties).
+type RecipientWithLabels interface {
+ WrapWithLabels(fileKey []byte) (s []*Stanza, labels []string, err error)
+}
+
// A Stanza is a section of the age header that encapsulates the file key as
// encrypted to a specific recipient.
//
@@ -111,27 +127,24 @@ func Encrypt(dst io.Writer, recipients ...Recipient) (io.WriteCloser, error) {
return nil, errors.New("no recipients specified")
}
- // As a best effort, prevent an API user from generating a file that the
- // ScryptIdentity will refuse to decrypt. This check can't unfortunately be
- // implemented as part of the Recipient interface, so it lives as a special
- // case in Encrypt.
- for _, r := range recipients {
- if _, ok := r.(*ScryptRecipient); ok && len(recipients) != 1 {
- return nil, errors.New("an ScryptRecipient must be the only one for the file")
- }
- }
-
fileKey := make([]byte, fileKeySize)
if _, err := rand.Read(fileKey); err != nil {
return nil, err
}
hdr := &format.Header{}
+ var labels []string
for i, r := range recipients {
- stanzas, err := r.Wrap(fileKey)
+ stanzas, l, err := wrapWithLabels(r, fileKey)
if err != nil {
return nil, fmt.Errorf("failed to wrap key for recipient #%d: %v", i, err)
}
+ sort.Strings(l)
+ if i == 0 {
+ labels = l
+ } else if !slicesEqual(labels, l) {
+ return nil, fmt.Errorf("incompatible recipients")
+ }
for _, s := range stanzas {
hdr.Recipients = append(hdr.Recipients, (*format.Stanza)(s))
}
@@ -156,6 +169,26 @@ func Encrypt(dst io.Writer, recipients ...Recipient) (io.WriteCloser, error) {
return stream.NewWriter(streamKey(fileKey, nonce), dst)
}
+func wrapWithLabels(r Recipient, fileKey []byte) (s []*Stanza, labels []string, err error) {
+ if r, ok := r.(RecipientWithLabels); ok {
+ return r.WrapWithLabels(fileKey)
+ }
+ s, err = r.Wrap(fileKey)
+ return
+}
+
+func slicesEqual(s1, s2 []string) bool {
+ if len(s1) != len(s2) {
+ return false
+ }
+ for i := range s1 {
+ if s1[i] != s2[i] {
+ return false
+ }
+ }
+ return true
+}
+
// NoIdentityMatchError is returned by Decrypt when none of the supplied
// identities match the encrypted file.
type NoIdentityMatchError struct {
diff --git a/vendor/filippo.io/age/internal/format/format.go b/vendor/filippo.io/age/internal/format/format.go
index aa77b756ff..0f22e6fa3a 100644
--- a/vendor/filippo.io/age/internal/format/format.go
+++ b/vendor/filippo.io/age/internal/format/format.go
@@ -201,7 +201,7 @@ func (r *StanzaReader) ReadStanza() (s *Stanza, err error) {
b, err := DecodeString(strings.TrimSuffix(string(line), "\n"))
if err != nil {
if bytes.HasPrefix(line, footerPrefix) || bytes.HasPrefix(line, stanzaPrefix) {
- return nil, fmt.Errorf("malformed body line %q: stanza ended without a short line\nNote: this might be a file encrypted with an old beta version of age or rage. Use age v1.0.0-beta6 or rage to decrypt it.", line)
+ return nil, fmt.Errorf("malformed body line %q: stanza ended without a short line\nnote: this might be a file encrypted with an old beta version of age or rage; use age v1.0.0-beta6 or rage to decrypt it", line)
}
return nil, errorf("malformed body line %q: %v", line, err)
}
diff --git a/vendor/filippo.io/age/internal/stream/stream.go b/vendor/filippo.io/age/internal/stream/stream.go
index 7cf02c470b..7551274bdb 100644
--- a/vendor/filippo.io/age/internal/stream/stream.go
+++ b/vendor/filippo.io/age/internal/stream/stream.go
@@ -12,7 +12,6 @@ import (
"io"
"golang.org/x/crypto/chacha20poly1305"
- "golang.org/x/crypto/poly1305"
)
const ChunkSize = 64 * 1024
@@ -29,7 +28,7 @@ type Reader struct {
}
const (
- encChunkSize = ChunkSize + poly1305.TagSize
+ encChunkSize = ChunkSize + chacha20poly1305.Overhead
lastChunkFlag = 0x01
)
diff --git a/vendor/filippo.io/age/scrypt.go b/vendor/filippo.io/age/scrypt.go
index 1346ad1388..73d13b7fad 100644
--- a/vendor/filippo.io/age/scrypt.go
+++ b/vendor/filippo.io/age/scrypt.go
@@ -6,6 +6,7 @@ package age
import (
"crypto/rand"
+ "encoding/hex"
"errors"
"fmt"
"regexp"
@@ -87,6 +88,29 @@ func (r *ScryptRecipient) Wrap(fileKey []byte) ([]*Stanza, error) {
return []*Stanza{l}, nil
}
+// WrapWithLabels implements [age.RecipientWithLabels], returning a random
+// label. This ensures a ScryptRecipient can't be mixed with other recipients
+// (including other ScryptRecipients).
+//
+// Users reasonably expect files encrypted to a passphrase to be [authenticated]
+// by that passphrase, i.e. for it to be impossible to produce a file that
+// decrypts successfully with a passphrase without knowing it. If a file is
+// encrypted to other recipients, those parties can produce different files that
+// would break that expectation.
+//
+// [authenticated]: https://words.filippo.io/dispatches/age-authentication/
+func (r *ScryptRecipient) WrapWithLabels(fileKey []byte) (stanzas []*Stanza, labels []string, err error) {
+ stanzas, err = r.Wrap(fileKey)
+
+ random := make([]byte, 16)
+ if _, err := rand.Read(random); err != nil {
+ return nil, nil, err
+ }
+ labels = []string{hex.EncodeToString(random)}
+
+ return
+}
+
// ScryptIdentity is a password-based identity.
type ScryptIdentity struct {
password []byte
diff --git a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
index 333676b7cf..c6e7c0d442 100644
--- a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
+++ b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
@@ -13,6 +13,7 @@ import (
"golang.org/x/tools/internal/gocommand"
)
+// TODO(adonovan): move back into go/packages.
func GetSizesForArgsGolist(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (string, string, error) {
inv.Verb = "list"
inv.Args = []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"}
diff --git a/vendor/golang.org/x/tools/go/packages/doc.go b/vendor/golang.org/x/tools/go/packages/doc.go
index a8d7b06ac0..3531ac8f5f 100644
--- a/vendor/golang.org/x/tools/go/packages/doc.go
+++ b/vendor/golang.org/x/tools/go/packages/doc.go
@@ -198,14 +198,6 @@ Instead, ssadump no longer requests the runtime package,
but seeks it among the dependencies of the user-specified packages,
and emits an error if it is not found.
-Overlays: The Overlay field in the Config allows providing alternate contents
-for Go source files, by providing a mapping from file path to contents.
-go/packages will pull in new imports added in overlay files when go/packages
-is run in LoadImports mode or greater.
-Overlay support for the go list driver isn't complete yet: if the file doesn't
-exist on disk, it will only be recognized in an overlay if it is a non-test file
-and the package would be reported even without the overlay.
-
Questions & Tasks
- Add GOARCH/GOOS?
diff --git a/vendor/golang.org/x/tools/go/packages/external.go b/vendor/golang.org/x/tools/go/packages/external.go
index 4335c1eb14..c2b4b711b5 100644
--- a/vendor/golang.org/x/tools/go/packages/external.go
+++ b/vendor/golang.org/x/tools/go/packages/external.go
@@ -34,8 +34,8 @@ type DriverRequest struct {
// Tests specifies whether the patterns should also return test packages.
Tests bool `json:"tests"`
- // Overlay maps file paths (relative to the driver's working directory) to the byte contents
- // of overlay files.
+ // Overlay maps file paths (relative to the driver's working directory)
+ // to the contents of overlay files (see Config.Overlay).
Overlay map[string][]byte `json:"overlay"`
}
@@ -119,7 +119,19 @@ func findExternalDriver(cfg *Config) driver {
stderr := new(bytes.Buffer)
cmd := exec.CommandContext(cfg.Context, tool, words...)
cmd.Dir = cfg.Dir
- cmd.Env = cfg.Env
+ // The cwd gets resolved to the real path. On Darwin, where
+ // /tmp is a symlink, this breaks anything that expects the
+ // working directory to keep the original path, including the
+ // go command when dealing with modules.
+ //
+ // os.Getwd stdlib has a special feature where if the
+ // cwd and the PWD are the same node then it trusts
+ // the PWD, so by setting it in the env for the child
+ // process we fix up all the paths returned by the go
+ // command.
+ //
+ // (See similar trick in Invocation.run in ../../internal/gocommand/invoke.go)
+ cmd.Env = append(slicesClip(cfg.Env), "PWD="+cfg.Dir)
cmd.Stdin = bytes.NewReader(req)
cmd.Stdout = buf
cmd.Stderr = stderr
@@ -138,3 +150,7 @@ func findExternalDriver(cfg *Config) driver {
return &response, nil
}
}
+
+// slicesClip removes unused capacity from the slice, returning s[:len(s):len(s)].
+// TODO(adonovan): use go1.21 slices.Clip.
+func slicesClip[S ~[]E, E any](s S) S { return s[:len(s):len(s)] }
diff --git a/vendor/golang.org/x/tools/go/packages/golist.go b/vendor/golang.org/x/tools/go/packages/golist.go
index 22305d9c90..d9be410aa1 100644
--- a/vendor/golang.org/x/tools/go/packages/golist.go
+++ b/vendor/golang.org/x/tools/go/packages/golist.go
@@ -841,6 +841,7 @@ func (state *golistState) cfgInvocation() gocommand.Invocation {
Env: cfg.Env,
Logf: cfg.Logf,
WorkingDir: cfg.Dir,
+ Overlay: cfg.goListOverlayFile,
}
}
@@ -849,26 +850,6 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer,
cfg := state.cfg
inv := state.cfgInvocation()
-
- // For Go versions 1.16 and above, `go list` accepts overlays directly via
- // the -overlay flag. Set it, if it's available.
- //
- // The check for "list" is not necessarily required, but we should avoid
- // getting the go version if possible.
- if verb == "list" {
- goVersion, err := state.getGoVersion()
- if err != nil {
- return nil, err
- }
- if goVersion >= 16 {
- filename, cleanup, err := state.writeOverlays()
- if err != nil {
- return nil, err
- }
- defer cleanup()
- inv.Overlay = filename
- }
- }
inv.Verb = verb
inv.Args = args
gocmdRunner := cfg.gocmdRunner
@@ -1015,67 +996,6 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer,
return stdout, nil
}
-// OverlayJSON is the format overlay files are expected to be in.
-// The Replace map maps from overlaid paths to replacement paths:
-// the Go command will forward all reads trying to open
-// each overlaid path to its replacement path, or consider the overlaid
-// path not to exist if the replacement path is empty.
-//
-// From golang/go#39958.
-type OverlayJSON struct {
- Replace map[string]string `json:"replace,omitempty"`
-}
-
-// writeOverlays writes out files for go list's -overlay flag, as described
-// above.
-func (state *golistState) writeOverlays() (filename string, cleanup func(), err error) {
- // Do nothing if there are no overlays in the config.
- if len(state.cfg.Overlay) == 0 {
- return "", func() {}, nil
- }
- dir, err := os.MkdirTemp("", "gopackages-*")
- if err != nil {
- return "", nil, err
- }
- // The caller must clean up this directory, unless this function returns an
- // error.
- cleanup = func() {
- os.RemoveAll(dir)
- }
- defer func() {
- if err != nil {
- cleanup()
- }
- }()
- overlays := map[string]string{}
- for k, v := range state.cfg.Overlay {
- // Create a unique filename for the overlaid files, to avoid
- // creating nested directories.
- noSeparator := strings.Join(strings.Split(filepath.ToSlash(k), "/"), "")
- f, err := os.CreateTemp(dir, fmt.Sprintf("*-%s", noSeparator))
- if err != nil {
- return "", func() {}, err
- }
- if _, err := f.Write(v); err != nil {
- return "", func() {}, err
- }
- if err := f.Close(); err != nil {
- return "", func() {}, err
- }
- overlays[k] = f.Name()
- }
- b, err := json.Marshal(OverlayJSON{Replace: overlays})
- if err != nil {
- return "", func() {}, err
- }
- // Write out the overlay file that contains the filepath mappings.
- filename = filepath.Join(dir, "overlay.json")
- if err := os.WriteFile(filename, b, 0665); err != nil {
- return "", func() {}, err
- }
- return filename, cleanup, nil
-}
-
func containsGoFile(s []string) bool {
for _, f := range s {
if strings.HasSuffix(f, ".go") {
diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go
index 3ea1b3fa46..34306ddd39 100644
--- a/vendor/golang.org/x/tools/go/packages/packages.go
+++ b/vendor/golang.org/x/tools/go/packages/packages.go
@@ -37,10 +37,20 @@ import (
// A LoadMode controls the amount of detail to return when loading.
// The bits below can be combined to specify which fields should be
// filled in the result packages.
+//
// The zero value is a special case, equivalent to combining
// the NeedName, NeedFiles, and NeedCompiledGoFiles bits.
+//
// ID and Errors (if present) will always be filled.
-// Load may return more information than requested.
+// [Load] may return more information than requested.
+//
+// Unfortunately there are a number of open bugs related to
+// interactions among the LoadMode bits:
+// - https://github.com/golang/go/issues/48226
+// - https://github.com/golang/go/issues/56633
+// - https://github.com/golang/go/issues/56677
+// - https://github.com/golang/go/issues/58726
+// - https://github.com/golang/go/issues/63517
type LoadMode int
const (
@@ -123,7 +133,14 @@ const (
// A Config specifies details about how packages should be loaded.
// The zero value is a valid configuration.
+//
// Calls to Load do not modify this struct.
+//
+// TODO(adonovan): #67702: this is currently false: in fact,
+// calls to [Load] do not modify the public fields of this struct, but
+// may modify hidden fields, so concurrent calls to [Load] must not
+// use the same Config. But perhaps we should reestablish the
+// documented invariant.
type Config struct {
// Mode controls the level of information returned for each package.
Mode LoadMode
@@ -199,13 +216,23 @@ type Config struct {
// setting Tests may have no effect.
Tests bool
- // Overlay provides a mapping of absolute file paths to file contents.
- // If the file with the given path already exists, the parser will use the
- // alternative file contents provided by the map.
+ // Overlay is a mapping from absolute file paths to file contents.
+ //
+ // For each map entry, [Load] uses the alternative file
+ // contents provided by the overlay mapping instead of reading
+ // from the file system. This mechanism can be used to enable
+ // editor-integrated tools to correctly analyze the contents
+ // of modified but unsaved buffers, for example.
//
- // Overlays provide incomplete support for when a given file doesn't
- // already exist on disk. See the package doc above for more details.
+ // The overlay mapping is passed to the build system's driver
+ // (see "The driver protocol") so that it too can report
+ // consistent package metadata about unsaved files. However,
+ // drivers may vary in their level of support for overlays.
Overlay map[string][]byte
+
+ // goListOverlayFile is the JSON file that encodes the Overlay
+ // mapping, used by 'go list -overlay=...'
+ goListOverlayFile string
}
// Load loads and returns the Go packages named by the given patterns.
@@ -213,6 +240,20 @@ type Config struct {
// Config specifies loading options;
// nil behaves the same as an empty Config.
//
+// The [Config.Mode] field is a set of bits that determine what kinds
+// of information should be computed and returned. Modes that require
+// more information tend to be slower. See [LoadMode] for details
+// and important caveats. Its zero value is equivalent to
+// NeedName | NeedFiles | NeedCompiledGoFiles.
+//
+// Each call to Load returns a new set of [Package] instances.
+// The Packages and their Imports form a directed acyclic graph.
+//
+// If the [NeedTypes] mode flag was set, each call to Load uses a new
+// [types.Importer], so [types.Object] and [types.Type] values from
+// different calls to Load must not be mixed as they will have
+// inconsistent notions of type identity.
+//
// If any of the patterns was invalid as defined by the
// underlying build system, Load returns an error.
// It may return an empty list of packages without an error,
@@ -286,6 +327,17 @@ func defaultDriver(cfg *Config, patterns ...string) (*DriverResponse, bool, erro
// (fall through)
}
+ // go list fallback
+ //
+ // Write overlays once, as there are many calls
+ // to 'go list' (one per chunk plus others too).
+ overlay, cleanupOverlay, err := gocommand.WriteOverlays(cfg.Overlay)
+ if err != nil {
+ return nil, false, err
+ }
+ defer cleanupOverlay()
+ cfg.goListOverlayFile = overlay
+
response, err := callDriverOnChunks(goListDriver, cfg, chunks)
if err != nil {
return nil, false, err
@@ -365,6 +417,9 @@ func mergeResponses(responses ...*DriverResponse) *DriverResponse {
}
// A Package describes a loaded Go package.
+//
+// It also defines part of the JSON schema of [DriverResponse].
+// See the package documentation for an overview.
type Package struct {
// ID is a unique identifier for a package,
// in a syntax provided by the underlying build system.
@@ -423,6 +478,13 @@ type Package struct {
// to corresponding loaded Packages.
Imports map[string]*Package
+ // Module is the module information for the package if it exists.
+ //
+ // Note: it may be missing for std and cmd; see Go issue #65816.
+ Module *Module
+
+ // -- The following fields are not part of the driver JSON schema. --
+
// Types provides type information for the package.
// The NeedTypes LoadMode bit sets this field for packages matching the
// patterns; type information for dependencies may be missing or incomplete,
@@ -431,15 +493,15 @@ type Package struct {
// Each call to [Load] returns a consistent set of type
// symbols, as defined by the comment at [types.Identical].
// Avoid mixing type information from two or more calls to [Load].
- Types *types.Package
+ Types *types.Package `json:"-"`
// Fset provides position information for Types, TypesInfo, and Syntax.
// It is set only when Types is set.
- Fset *token.FileSet
+ Fset *token.FileSet `json:"-"`
// IllTyped indicates whether the package or any dependency contains errors.
// It is set only when Types is set.
- IllTyped bool
+ IllTyped bool `json:"-"`
// Syntax is the package's syntax trees, for the files listed in CompiledGoFiles.
//
@@ -449,26 +511,28 @@ type Package struct {
//
// Syntax is kept in the same order as CompiledGoFiles, with the caveat that nils are
// removed. If parsing returned nil, Syntax may be shorter than CompiledGoFiles.
- Syntax []*ast.File
+ Syntax []*ast.File `json:"-"`
// TypesInfo provides type information about the package's syntax trees.
// It is set only when Syntax is set.
- TypesInfo *types.Info
+ TypesInfo *types.Info `json:"-"`
// TypesSizes provides the effective size function for types in TypesInfo.
- TypesSizes types.Sizes
+ TypesSizes types.Sizes `json:"-"`
+
+ // -- internal --
// forTest is the package under test, if any.
forTest string
// depsErrors is the DepsErrors field from the go list response, if any.
depsErrors []*packagesinternal.PackageError
-
- // module is the module information for the package if it exists.
- Module *Module
}
// Module provides module information for a package.
+//
+// It also defines part of the JSON schema of [DriverResponse].
+// See the package documentation for an overview.
type Module struct {
Path string // module path
Version string // module version
@@ -601,6 +665,7 @@ func (p *Package) UnmarshalJSON(b []byte) error {
OtherFiles: flat.OtherFiles,
EmbedFiles: flat.EmbedFiles,
EmbedPatterns: flat.EmbedPatterns,
+ IgnoredFiles: flat.IgnoredFiles,
ExportFile: flat.ExportFile,
}
if len(flat.Imports) > 0 {
diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/vendor/golang.org/x/tools/internal/gocommand/invoke.go
index eb7a8282f9..af0ee6c614 100644
--- a/vendor/golang.org/x/tools/internal/gocommand/invoke.go
+++ b/vendor/golang.org/x/tools/internal/gocommand/invoke.go
@@ -8,12 +8,14 @@ package gocommand
import (
"bytes"
"context"
+ "encoding/json"
"errors"
"fmt"
"io"
"log"
"os"
"os/exec"
+ "path/filepath"
"reflect"
"regexp"
"runtime"
@@ -167,7 +169,9 @@ type Invocation struct {
// TODO(rfindley): remove, in favor of Args.
ModFile string
- // If Overlay is set, the go command is invoked with -overlay=Overlay.
+ // Overlay is the name of the JSON overlay file that describes
+ // unsaved editor buffers; see [WriteOverlays].
+ // If set, the go command is invoked with -overlay=Overlay.
// TODO(rfindley): remove, in favor of Args.
Overlay string
@@ -255,12 +259,15 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
waitDelay.Set(reflect.ValueOf(30 * time.Second))
}
- // On darwin the cwd gets resolved to the real path, which breaks anything that
- // expects the working directory to keep the original path, including the
+ // The cwd gets resolved to the real path. On Darwin, where
+ // /tmp is a symlink, this breaks anything that expects the
+ // working directory to keep the original path, including the
// go command when dealing with modules.
- // The Go stdlib has a special feature where if the cwd and the PWD are the
- // same node then it trusts the PWD, so by setting it in the env for the child
- // process we fix up all the paths returned by the go command.
+ //
+ // os.Getwd has a special feature where if the cwd and the PWD
+ // are the same node then it trusts the PWD, so by setting it
+ // in the env for the child process we fix up all the paths
+ // returned by the go command.
if !i.CleanEnv {
cmd.Env = os.Environ()
}
@@ -351,6 +358,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
}
}
+ startTime := time.Now()
err = cmd.Start()
if stdoutW != nil {
// The child process has inherited the pipe file,
@@ -377,7 +385,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
case err := <-resChan:
return err
case <-timer.C:
- HandleHangingGoCommand(cmd.Process)
+ HandleHangingGoCommand(startTime, cmd)
case <-ctx.Done():
}
} else {
@@ -411,7 +419,7 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) (err error) {
return <-resChan
}
-func HandleHangingGoCommand(proc *os.Process) {
+func HandleHangingGoCommand(start time.Time, cmd *exec.Cmd) {
switch runtime.GOOS {
case "linux", "darwin", "freebsd", "netbsd":
fmt.Fprintln(os.Stderr, `DETECTED A HANGING GO COMMAND
@@ -444,7 +452,7 @@ See golang/go#54461 for more details.`)
panic(fmt.Sprintf("running %s: %v", listFiles, err))
}
}
- panic(fmt.Sprintf("detected hanging go command (pid %d): see golang/go#54461 for more details", proc.Pid))
+ panic(fmt.Sprintf("detected hanging go command (golang/go#54461); waited %s\n\tcommand:%s\n\tpid:%d", time.Since(start), cmd, cmd.Process.Pid))
}
func cmdDebugStr(cmd *exec.Cmd) string {
@@ -468,3 +476,73 @@ func cmdDebugStr(cmd *exec.Cmd) string {
}
return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " "))
}
+
+// WriteOverlays writes each value in the overlay (see the Overlay
+// field of go/packages.Config) to a temporary file and returns the name
+// of a JSON file describing the mapping that is suitable for the "go
+// list -overlay" flag.
+//
+// On success, the caller must call the cleanup function exactly once
+// when the files are no longer needed.
+func WriteOverlays(overlay map[string][]byte) (filename string, cleanup func(), err error) {
+ // Do nothing if there are no overlays in the config.
+ if len(overlay) == 0 {
+ return "", func() {}, nil
+ }
+
+ dir, err := os.MkdirTemp("", "gocommand-*")
+ if err != nil {
+ return "", nil, err
+ }
+
+ // The caller must clean up this directory,
+ // unless this function returns an error.
+ // (The cleanup operand of each return
+ // statement below is ignored.)
+ defer func() {
+ cleanup = func() {
+ os.RemoveAll(dir)
+ }
+ if err != nil {
+ cleanup()
+ cleanup = nil
+ }
+ }()
+
+ // Write each map entry to a temporary file.
+ overlays := make(map[string]string)
+ for k, v := range overlay {
+ // Use a unique basename for each file (001-foo.go),
+ // to avoid creating nested directories.
+ base := fmt.Sprintf("%d-%s.go", 1+len(overlays), filepath.Base(k))
+ filename := filepath.Join(dir, base)
+ err := os.WriteFile(filename, v, 0666)
+ if err != nil {
+ return "", nil, err
+ }
+ overlays[k] = filename
+ }
+
+ // Write the JSON overlay file that maps logical file names to temp files.
+ //
+ // OverlayJSON is the format overlay files are expected to be in.
+ // The Replace map maps from overlaid paths to replacement paths:
+ // the Go command will forward all reads trying to open
+ // each overlaid path to its replacement path, or consider the overlaid
+ // path not to exist if the replacement path is empty.
+ //
+ // From golang/go#39958.
+ type OverlayJSON struct {
+ Replace map[string]string `json:"replace,omitempty"`
+ }
+ b, err := json.Marshal(OverlayJSON{Replace: overlays})
+ if err != nil {
+ return "", nil, err
+ }
+ filename = filepath.Join(dir, "overlay.json")
+ if err := os.WriteFile(filename, b, 0666); err != nil {
+ return "", nil, err
+ }
+
+ return filename, nil, nil
+}
diff --git a/vendor/golang.org/x/tools/internal/versions/types_go122.go b/vendor/golang.org/x/tools/internal/versions/types_go122.go
index e8180632a5..aac5db62c9 100644
--- a/vendor/golang.org/x/tools/internal/versions/types_go122.go
+++ b/vendor/golang.org/x/tools/internal/versions/types_go122.go
@@ -12,7 +12,7 @@ import (
"go/types"
)
-// FileVersions returns a file's Go version.
+// FileVersion returns a file's Go version.
// The reported version is an unknown Future version if a
// version cannot be determined.
func FileVersion(info *types.Info, file *ast.File) string {
diff --git a/vendor/modules.txt b/vendor/modules.txt
index e1fac98118..cad3ecfb26 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1,6 +1,6 @@
# cloud.google.com/go/compute/metadata v0.2.3
## explicit; go 1.19
-# filippo.io/age v1.1.1
+# filippo.io/age v1.2.1
## explicit; go 1.19
filippo.io/age
filippo.io/age/internal/bech32
@@ -821,7 +821,7 @@ golang.org/x/exp/slices
golang.org/x/exp/slog
golang.org/x/exp/slog/internal
golang.org/x/exp/slog/internal/buffer
-# golang.org/x/mod v0.17.0
+# golang.org/x/mod v0.18.0
## explicit; go 1.18
golang.org/x/mod/semver
# golang.org/x/net v0.26.0
@@ -883,7 +883,7 @@ golang.org/x/text/width
# golang.org/x/time v0.5.0
## explicit; go 1.18
golang.org/x/time/rate
-# golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
+# golang.org/x/tools v0.22.0
## explicit; go 1.19
golang.org/x/tools/go/gcexportdata
golang.org/x/tools/go/internal/packagesdriver