├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── .golangci.yaml ├── .husky.toml ├── .version ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── cmd └── cuem │ ├── cmd │ ├── app.go │ ├── cmd_eval.go │ ├── cmd_fmt.go │ ├── cmd_gen.go │ ├── cmd_get.go │ └── common.go │ └── main.go ├── cue.mod ├── .gitignore └── module.cue ├── go.mod ├── go.sum ├── internal ├── cmd │ ├── go │ │ └── internals │ │ │ ├── auth │ │ │ ├── auth.go │ │ │ └── netrc.go │ │ │ ├── base │ │ │ ├── base.go │ │ │ ├── env.go │ │ │ ├── flag.go │ │ │ ├── goflags.go │ │ │ ├── limit.go │ │ │ ├── path.go │ │ │ ├── signal.go │ │ │ ├── signal_notunix.go │ │ │ ├── signal_unix.go │ │ │ └── tool.go │ │ │ ├── cache │ │ │ ├── cache.go │ │ │ ├── default.go │ │ │ ├── hash.go │ │ │ └── prog.go │ │ │ ├── cfg │ │ │ ├── cfg.go │ │ │ ├── lookpath.go │ │ │ └── zdefaultcc.go │ │ │ ├── fsys │ │ │ └── fsys.go │ │ │ ├── gover │ │ │ ├── gomod.go │ │ │ ├── gover.go │ │ │ ├── local.go │ │ │ ├── mod.go │ │ │ ├── toolchain.go │ │ │ └── version.go │ │ │ ├── imports │ │ │ ├── build.go │ │ │ ├── read.go │ │ │ ├── scan.go │ │ │ └── tags.go │ │ │ ├── lockedfile │ │ │ ├── internals │ │ │ │ └── filelock │ │ │ │ │ ├── filelock.go │ │ │ │ │ ├── filelock_fcntl.go │ │ │ │ │ ├── filelock_other.go │ │ │ │ │ ├── filelock_unix.go │ │ │ │ │ └── filelock_windows.go │ │ │ ├── lockedfile.go │ │ │ ├── lockedfile_filelock.go │ │ │ ├── lockedfile_plan9.go │ │ │ └── mutex.go │ │ │ ├── mmap │ │ │ ├── mmap.go │ │ │ ├── mmap_other.go │ │ │ ├── mmap_unix.go │ │ │ └── mmap_windows.go │ │ │ ├── modfetch │ │ │ ├── bootstrap.go │ │ │ ├── cache.go │ │ │ ├── codehost │ │ │ │ ├── codehost.go │ │ │ │ ├── git.go │ │ │ │ ├── svn.go │ │ │ │ └── vcs.go │ │ │ ├── coderepo.go │ │ │ ├── fetch.go │ │ │ ├── key.go │ │ │ ├── proxy.go │ │ │ ├── repo.go │ │ │ ├── sumdb.go │ │ │ └── toolchain.go │ │ │ ├── modindex │ │ │ ├── build.go │ │ │ ├── build_read.go │ │ │ ├── read.go │ │ │ ├── scan.go │ │ │ ├── syslist.go │ │ │ └── write.go │ │ │ ├── modinfo │ │ │ └── info.go │ │ │ ├── modload │ │ │ ├── build.go │ │ │ ├── buildlist.go │ │ │ ├── edit.go │ │ │ ├── help.go │ │ │ ├── import.go │ │ │ ├── init.go │ │ │ ├── list.go │ │ │ ├── load.go │ │ │ ├── modfile.go │ │ │ ├── mvs.go │ │ │ ├── query.go │ │ │ ├── search.go │ │ │ ├── stat_openfile.go │ │ │ ├── stat_unix.go │ │ │ ├── stat_windows.go │ │ │ └── vendor.go │ │ │ ├── mvs │ │ │ ├── errors.go │ │ │ ├── graph.go │ │ │ └── mvs.go │ │ │ ├── par │ │ │ ├── queue.go │ │ │ └── work.go │ │ │ ├── robustio │ │ │ ├── robustio.go │ │ │ ├── robustio_darwin.go │ │ │ ├── robustio_flaky.go │ │ │ ├── robustio_other.go │ │ │ └── robustio_windows.go │ │ │ ├── search │ │ │ └── search.go │ │ │ ├── str │ │ │ ├── path.go │ │ │ └── str.go │ │ │ ├── trace │ │ │ └── trace.go │ │ │ ├── vcs │ │ │ ├── discovery.go │ │ │ └── vcs.go │ │ │ └── web │ │ │ ├── api.go │ │ │ ├── bootstrap.go │ │ │ ├── http.go │ │ │ ├── url.go │ │ │ ├── url_other.go │ │ │ └── url_windows.go │ └── internals │ │ ├── browser │ │ └── browser.go │ │ ├── pkgpattern │ │ └── pkgpattern.go │ │ └── quoted │ │ └── quoted.go ├── internals │ ├── bisect │ │ └── bisect.go │ ├── buildcfg │ │ ├── cfg.go │ │ ├── exp.go │ │ └── zbootstrap.go │ ├── cfg │ │ └── cfg.go │ ├── godebug │ │ └── godebug.go │ ├── godebugs │ │ └── table.go │ ├── goexperiment │ │ ├── exp_allocheaders_off.go │ │ ├── exp_allocheaders_on.go │ │ ├── exp_arenas_off.go │ │ ├── exp_arenas_on.go │ │ ├── exp_boringcrypto_off.go │ │ ├── exp_boringcrypto_on.go │ │ ├── exp_cacheprog_off.go │ │ ├── exp_cacheprog_on.go │ │ ├── exp_cgocheck2_off.go │ │ ├── exp_cgocheck2_on.go │ │ ├── exp_coverageredesign_off.go │ │ ├── exp_coverageredesign_on.go │ │ ├── exp_exectracer2_off.go │ │ ├── exp_exectracer2_on.go │ │ ├── exp_fieldtrack_off.go │ │ ├── exp_fieldtrack_on.go │ │ ├── exp_heapminimum512kib_off.go │ │ ├── exp_heapminimum512kib_on.go │ │ ├── exp_loopvar_off.go │ │ ├── exp_loopvar_on.go │ │ ├── exp_newinliner_off.go │ │ ├── exp_newinliner_on.go │ │ ├── exp_pagetrace_off.go │ │ ├── exp_pagetrace_on.go │ │ ├── exp_preemptibleloops_off.go │ │ ├── exp_preemptibleloops_on.go │ │ ├── exp_rangefunc_off.go │ │ ├── exp_rangefunc_on.go │ │ ├── exp_regabiargs_off.go │ │ ├── exp_regabiargs_on.go │ │ ├── exp_regabiwrappers_off.go │ │ ├── exp_regabiwrappers_on.go │ │ ├── exp_staticlockranking_off.go │ │ ├── exp_staticlockranking_on.go │ │ └── flags.go │ ├── goroot │ │ ├── gc.go │ │ └── gccgo.go │ ├── gover │ │ └── gover.go │ ├── goversion │ │ └── goversion.go │ ├── lazyregexp │ │ └── lazyre.go │ ├── singleflight │ │ └── singleflight.go │ ├── syscall │ │ └── windows │ │ │ ├── memory_windows.go │ │ │ ├── mksyscall.go │ │ │ ├── net_windows.go │ │ │ ├── psapi_windows.go │ │ │ ├── reparse_windows.go │ │ │ ├── security_windows.go │ │ │ ├── symlink_windows.go │ │ │ ├── syscall_windows.go │ │ │ ├── sysdll │ │ │ └── sysdll.go │ │ │ └── zsyscall_windows.go │ └── trace │ │ └── traceviewer │ │ └── format │ │ └── format.go └── version │ └── version.go ├── pkg ├── cli │ ├── app.go │ ├── interface.go │ └── name.go ├── cueify │ ├── core │ │ ├── extractor.go │ │ └── util.go │ ├── crd │ │ ├── extractor.go │ │ ├── extractor_test.go │ │ └── testdata │ │ │ ├── gen │ │ │ ├── .sum │ │ │ └── servicemonitors.monitoring.coreos.com_gen.cue │ │ │ └── src │ │ │ └── servicemonitors.yaml │ ├── golang │ │ ├── astutil.go │ │ ├── extractor.go │ │ ├── extractor_test.go │ │ ├── fake_importer.go │ │ ├── func_method.go │ │ ├── group_version.go │ │ ├── import_paths.go │ │ ├── pkg_extractor.go │ │ ├── std │ │ │ ├── list.go │ │ │ ├── list.sh │ │ │ └── list.txt │ │ └── testdata │ │ │ ├── gen │ │ │ ├── .sum │ │ │ ├── enums_go_gen.cue │ │ │ ├── types_go_gen.cue │ │ │ └── values_go_gen.cue │ │ │ └── src │ │ │ ├── enums.go │ │ │ ├── types.go │ │ │ └── values.go │ └── register.go ├── cuemod │ ├── build.go │ ├── builtin │ │ ├── builtins.go │ │ ├── builtins.txt │ │ └── builtins_test.go │ ├── context.go │ ├── context_test.go │ ├── mod.go │ ├── mod │ │ └── mod.go │ ├── mod_resolver.go │ ├── mod_resolver_test.go │ ├── modfile │ │ ├── load.go │ │ ├── load_test.go │ │ ├── modfile.go │ │ └── path_may_with_version.go │ ├── options.go │ ├── path.go │ ├── stdlib │ │ └── stdlib.go │ ├── testdata │ │ ├── a │ │ │ ├── cue.mod │ │ │ │ ├── .gitignore │ │ │ │ ├── module.cue │ │ │ │ └── module.sum │ │ │ ├── defs.cue │ │ │ └── main.cue │ │ ├── b │ │ │ ├── cue.mod │ │ │ │ ├── .gitignore │ │ │ │ ├── module.cue │ │ │ │ ├── module.sum │ │ │ │ └── usr │ │ │ │ │ └── github.com │ │ │ │ │ └── x │ │ │ │ │ └── b │ │ │ ├── cuepkg │ │ │ │ └── c │ │ │ │ │ ├── c.cue │ │ │ │ │ └── cue.mod │ │ │ │ │ ├── .gitignore │ │ │ │ │ ├── module.cue │ │ │ │ │ └── module.sum │ │ │ └── main.cue │ │ └── embedstdlib │ │ │ ├── pkg.go │ │ │ └── std.x.io │ │ │ └── a │ │ │ └── hello.cue │ └── util.go ├── cuemodx │ └── eval.go ├── cuex │ ├── build.go │ ├── build_test.go │ ├── bundle.go │ ├── eval.go │ └── format │ │ └── format.go ├── modutil │ ├── revinfo.go │ ├── revinfo.s │ ├── revinfo_test.go │ ├── util.go │ └── util_test.go └── version │ ├── version.go │ └── version_test.go ├── tool └── internalfork │ └── main.go └── wagon.cue /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | 8 | - package-ecosystem: "gomod" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - "*" 7 | tags: 8 | - 'v*' 9 | 10 | jobs: 11 | ci: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: docker/setup-qemu-action@v2 16 | 17 | - run: curl -sSLf https://raw.githubusercontent.com/octohelm/wagon/main/install.sh | sudo sh 18 | 19 | - run: make archive 20 | env: 21 | GH_USERNAME: ${{ github.actor }} 22 | GH_PASSWORD: ${{ secrets.GITHUB_TOKEN }} 23 | 24 | - uses: "marvinpinto/action-automatic-releases@latest" 25 | if: ${{ !startsWith(github.ref, 'refs/tags/v') }} 26 | with: 27 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 28 | prerelease: true 29 | automatic_release_tag: "latest" 30 | files: | 31 | .wagon/output/*.tar.gz 32 | 33 | - uses: "marvinpinto/action-automatic-releases@latest" 34 | if: ${{ startsWith(github.ref, 'refs/tags/v') }} 35 | with: 36 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 37 | files: | 38 | .wagon/output/*.tar.gz 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .wagon/ 3 | 4 | bin/ 5 | vendor/ 6 | jsonnetpkg/ 7 | 8 | coverage.txt -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | run: 2 | skip-dirs: 3 | - internal -------------------------------------------------------------------------------- /.husky.toml: -------------------------------------------------------------------------------- 1 | [hooks] 2 | 3 | pre-commit = [ 4 | # "golangci-lint run", 5 | "husky lint-staged" 6 | ] 7 | 8 | commit-msg = [ 9 | "husky lint-commit" 10 | ] 11 | 12 | [lint-staged] 13 | "{pkg/,cmd/}{**/}*.go" = [ 14 | "goimports -l -w" 15 | ] 16 | -------------------------------------------------------------------------------- /.version: -------------------------------------------------------------------------------- 1 | 0.8.1 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 cuemod 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | WAGON=wagon -p ./wagon.cue 2 | CUEM = go run ./cmd/cuem 3 | 4 | INTERNAL_FORK = go run ./tool/internalfork 5 | 6 | fork.go.internal: 7 | $(INTERNAL_FORK) \ 8 | -p cmd/go/internal/modload \ 9 | -p cmd/go/internal/modfetch \ 10 | -p internal/godebug \ 11 | ./internal 12 | 13 | ship: 14 | $(WAGON) do go ship pushx 15 | 16 | archive: 17 | $(WAGON) do go archive --output ./.wagon/output 18 | 19 | install: 20 | go install ./cmd/cuem 21 | 22 | fmt: 23 | goimports -l -w . 24 | 25 | tidy: 26 | go mod tidy 27 | 28 | test: 29 | go test -failfast ./pkg/... 30 | 31 | dep: 32 | go get -u -t ./cmd/... 33 | 34 | cuem.fmt: 35 | $(CUEM) fmt -l -w ./... 36 | 37 | cuem.get.u: 38 | $(CUEM) get -u ./... 39 | 40 | cuem.get: 41 | $(CUEM) get -i=go k8s.io/api k8s.io/apimachinery 42 | $(CUEM) get github.com/innoai-tech/runtime@main 43 | 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CUE Mod 2 | 3 | [![GoDoc Widget](https://godoc.org/github.com/octohelm/cuemod?status.svg)](https://pkg.go.dev/github.com/octohelm/cuemod) 4 | [![Go Report Card](https://goreportcard.com/badge/github.com/octohelm/cuemod)](https://goreportcard.com/report/github.com/octohelm/cuemod) 5 | 6 | **ALPHA VERSION** 7 | 8 | **May deprecated when [cue modules official supported](https://github.com/cue-lang/cue/issues/851)** 9 | 10 | dependency management for [CUE](https://cuelang.org/) without committing `cue.mod` 11 | 12 | ## Requirements 13 | 14 | * `git` or other vcs tool supported by go for vcs downloading. 15 | 16 | ## Install 17 | 18 | ```shell 19 | go install github.com/octohelm/cuemod/cmd/cuem@latest 20 | ``` 21 | 22 | ## Usage 23 | 24 | ### Quick Start 25 | 26 | ```bash 27 | mkdir -p ./demo && cd ./demo 28 | 29 | cat << EOT > kube.cue 30 | package kube 31 | 32 | import ( 33 | apps_v1 "k8s.io/api/apps/v1" 34 | ) 35 | 36 | deployment: [string]: apps_v1.#Deployment 37 | 38 | _labels: { "app": "nginx" } 39 | 40 | deployment: nginx: spec: selector: matchLabels: _labels 41 | deployment: nginx: spec: template: metadata: labels: _labels 42 | deployment: nginx: spec: template: spec: { 43 | containers: [{ 44 | name: "nginx" 45 | image: "nginx:1.11.10-alpine" 46 | }] 47 | } 48 | EOT 49 | 50 | cuem eval -o kube.yaml ./kube.cue 51 | # build, will automately install deps if not exists or generator if needed. 52 | 53 | cuem eval -o ./kube.single-file.cue ./kube.cue 54 | # will bundle to one single cue file 55 | ``` 56 | 57 | ### Dependency management 58 | 59 | ```bash 60 | # auto added deps 61 | cuem get ./... 62 | 63 | # upgrade deps 64 | cuem get -u ./... 65 | 66 | # install dep with special version 67 | cuem get github.com/grafana/jsonnet-libs@latest 68 | ``` 69 | 70 | ## Features 71 | 72 | * Dependency management based on go modules 73 | * all dependency codes will download under `$(go env GOMODCACHE)` 74 | * `GOPROXY` supported to speed up downloading 75 | * Extract to cue pkg from other language or schema spec. 76 | * `golang` supported 77 | * k8s `crd` json supported 78 | 79 | ## Spec `cue.mod/module.cue` 80 | 81 | ```cue 82 | // module name 83 | // for sub mod import, /path/to/sub 84 | // NOTICE: the module name should be a valid repo name 85 | module: "github.com/octohelm/cuemod" 86 | 87 | require: { 88 | "dagger.io": "v0.2.8-0.20220512005159-64cb4f755695" 89 | "k8s.io/api": "v0.24.0" 90 | "universe.dagger.io": "v0.2.8-0.20220512005159-64cb4f755695" 91 | } 92 | 93 | require: { 94 | "k8s.io/apimachinery": "v0.24.0" @indirect() 95 | } 96 | 97 | replace: { 98 | // replace module with spec version 99 | "dagger.io": "github.com/morlay/dagger/pkg/dagger.io@#release-main" 100 | "universe.dagger.io": "github.com/morlay/dagger/pkg/universe.dagger.io@#release-main" 101 | 102 | // **notice** only works for current mod 103 | "github.com/x/a": "../a" 104 | } 105 | 106 | replace: { 107 | "k8s.io/api": "" @import("go") 108 | "k8s.io/apimachinery": "" @import("go") 109 | } 110 | 111 | ``` 112 | 113 | ### Known issues 114 | 115 | #### pkg name may not same as path 116 | 117 | Some path like `github.com/istio/istio/manifests/charts/istio-operator`, the `istio-operator` is not a valid identifier 118 | in `cue-lang`. Should import with `github.com/istio/istio/manifests/charts/istio-operator:istio_operator` 119 | -------------------------------------------------------------------------------- /cmd/cuem/cmd/app.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "context" 5 | "os" 6 | 7 | "github.com/octohelm/cuemod/internal/version" 8 | "github.com/octohelm/cuemod/pkg/cli" 9 | ) 10 | 11 | var app = cli.NewApp("cuemod", version.Version(), &ProjectFlags{}) 12 | 13 | func Run(ctx context.Context) error { 14 | return app.Run(ctx, os.Args) 15 | } 16 | -------------------------------------------------------------------------------- /cmd/cuem/cmd/cmd_eval.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "io" 7 | "os" 8 | "path/filepath" 9 | 10 | "github.com/octohelm/cuemod/pkg/cuemodx" 11 | 12 | "github.com/octohelm/cuemod/pkg/cli" 13 | "github.com/octohelm/cuemod/pkg/cuemod" 14 | "github.com/octohelm/cuemod/pkg/cuex" 15 | ) 16 | 17 | func init() { 18 | app.Add(&Eval{}) 19 | } 20 | 21 | type EvalFlags struct { 22 | Output string `flag:"output,o" desc:"output filename and fmt"` 23 | Write bool `flag:"write,w" desc:"write"` 24 | } 25 | 26 | type Eval struct { 27 | cli.Name `args:"CUE_FILES..." desc:"evalWithPatches files"` 28 | EvalFlags 29 | } 30 | 31 | func (opts *Eval) Run(ctx context.Context, args []string) error { 32 | results, err := evalWithPatches(ctx, args, cuex.WithEncodingFromFileExt(filepath.Ext(opts.Output))) 33 | if err != nil { 34 | return err 35 | } 36 | 37 | if opts.Output != "" && opts.Write { 38 | if err := writeFile(opts.Output, results); err != nil { 39 | return err 40 | } 41 | } else { 42 | _, _ = io.Copy(os.Stdout, bytes.NewBuffer(results)) 43 | } 44 | 45 | return nil 46 | } 47 | 48 | func evalWithPatches(ctx context.Context, fileOrPatches []string, options ...cuex.EvalOptionFunc) ([]byte, error) { 49 | cc := cuemod.FromContext(ctx) 50 | 51 | cwd, _ := os.Getwd() 52 | for i := range fileOrPatches { 53 | if fileOrPatches[i][0] == '.' { 54 | fileOrPatches[i] = filepath.Join(cwd, fileOrPatches[i]) 55 | } 56 | } 57 | 58 | return cuemodx.EvalContextWithPatches(ctx, cc, fileOrPatches, options...) 59 | } 60 | 61 | func writeFile(filename string, data []byte) error { 62 | if err := os.MkdirAll(filepath.Dir(filename), os.ModePerm); err != nil { 63 | return err 64 | } 65 | return os.WriteFile(filename, data, os.ModePerm) 66 | } 67 | -------------------------------------------------------------------------------- /cmd/cuem/cmd/cmd_fmt.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/octohelm/cuemod/pkg/cli" 7 | "github.com/octohelm/cuemod/pkg/cuemod" 8 | 9 | "github.com/octohelm/cuemod/pkg/cuex/format" 10 | ) 11 | 12 | func init() { 13 | app.Add(&Fmt{}) 14 | } 15 | 16 | type Fmt struct { 17 | cli.Name `args:"BASE_DIR" desc:"base dir for files fmt"` 18 | format.FormatOpts 19 | } 20 | 21 | func (opts *Fmt) Run(ctx context.Context, args []string) error { 22 | baseDir := "./" 23 | if len(args) > 0 { 24 | baseDir = args[0] 25 | } 26 | 27 | files, err := cuemod.FromContext(ctx).ListCue(baseDir) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | return format.FormatFiles(ctx, files, opts.FormatOpts) 33 | } 34 | -------------------------------------------------------------------------------- /cmd/cuem/cmd/cmd_gen.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/octohelm/cuemod/pkg/cueify" 7 | 8 | "github.com/octohelm/cuemod/pkg/cli" 9 | ) 10 | 11 | func init() { 12 | app.Add(&Gen{}) 13 | } 14 | 15 | type Gen struct { 16 | cli.Name `args:"PATH" desc:"source path"` 17 | Output string `flag:"output,o" desc:"generate output"` 18 | Import string `flag:"import,i" desc:"declare language for generate. support values: crd | go"` 19 | } 20 | 21 | func (o *Gen) Run(ctx context.Context, args []string) error { 22 | return cueify.ExtractToDir( 23 | ctx, 24 | o.Import, 25 | args[0], 26 | o.Output, 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /cmd/cuem/cmd/cmd_get.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/octohelm/cuemod/pkg/cli" 7 | "github.com/octohelm/cuemod/pkg/cuemod" 8 | ) 9 | 10 | func init() { 11 | app.Add(&Get{}) 12 | } 13 | 14 | type Get struct { 15 | cli.Name `args:"IMPORT_PATH..." desc:"download dependencies"` 16 | Upgrade bool `flag:"upgrade,u" desc:"upgrade dependencies"` 17 | Import string `flag:"import,i" desc:"declare language for generate. support values: crd | go"` 18 | } 19 | 20 | func (o *Get) Run(ctx context.Context, args []string) error { 21 | cc := cuemod.FromContext(ctx) 22 | 23 | for i := range args { 24 | p := args[i] 25 | err := cc.Get( 26 | cuemod.WithOpts(ctx, 27 | cuemod.OptUpgrade(o.Upgrade), 28 | cuemod.OptImport(o.Import), 29 | cuemod.OptVerbose(true), 30 | ), p, 31 | ) 32 | if err != nil { 33 | return err 34 | } 35 | } 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /cmd/cuem/cmd/common.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "context" 5 | 6 | xslog "log/slog" 7 | 8 | "github.com/go-courier/logr" 9 | "github.com/go-courier/logr/slog" 10 | "github.com/octohelm/cuemod/pkg/cuemod" 11 | ) 12 | 13 | type ProjectFlags struct { 14 | Root string `flag:"!project,p" desc:"project root"` 15 | V int `flag:"!verbose,v" desc:"verbose level"` 16 | } 17 | 18 | func (v ProjectFlags) PreRun(ctx context.Context) context.Context { 19 | ctx = cuemod.InjectContext(ctx, cuemod.ContextFor(v.Root)) 20 | if v.V > 0 { 21 | return logr.WithLogger(ctx, slog.Logger(slog.Default())) 22 | } 23 | return logr.WithLogger(ctx, slog.Logger(xslog.New(xslog.Default().Handler()))) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/cuem/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/octohelm/cuemod/cmd/cuem/cmd" 7 | ) 8 | 9 | func main() { 10 | if err := cmd.Run(context.Background()); err != nil { 11 | panic(err) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /cue.mod/.gitignore: -------------------------------------------------------------------------------- 1 | gen/ 2 | pkg/ 3 | module.sum -------------------------------------------------------------------------------- /cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "github.com/octohelm/cuemod" 2 | 3 | require: { 4 | "github.com/innoai-tech/runtime": "v0.0.0-20230807071635-a566ade1c374" 5 | "wagon.octohelm.tech": "v0.0.0" 6 | } 7 | 8 | replace: { 9 | "k8s.io/api": "" @import("go") 10 | "k8s.io/apimachinery": "" @import("go") 11 | } 12 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/octohelm/cuemod 2 | 3 | go 1.22 4 | 5 | require ( 6 | cuelang.org/go v0.7.1 7 | github.com/go-courier/logr v0.3.0 8 | github.com/octohelm/x v0.0.0-20231115103341-17be3238221d 9 | github.com/onsi/gomega v1.30.0 10 | github.com/pkg/errors v0.9.1 11 | github.com/spf13/cobra v1.8.0 12 | github.com/spf13/pflag v1.0.5 13 | golang.org/x/mod v0.15.0 14 | golang.org/x/tools v0.16.1 15 | k8s.io/apiextensions-apiserver v0.29.2 16 | k8s.io/apimachinery v0.29.2 17 | sigs.k8s.io/yaml v1.4.0 18 | ) 19 | 20 | require ( 21 | cuelabs.dev/go/oci/ociregistry v0.0.0-20231217163254-6feb86eb6e06 // indirect 22 | github.com/cockroachdb/apd/v3 v3.2.1 // indirect 23 | github.com/emicklei/proto v1.13.2 // indirect 24 | github.com/go-logr/logr v1.4.1 // indirect 25 | github.com/gogo/protobuf v1.3.2 // indirect 26 | github.com/google/go-cmp v0.6.0 // indirect 27 | github.com/google/gofuzz v1.2.0 // indirect 28 | github.com/google/uuid v1.6.0 // indirect 29 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 30 | github.com/json-iterator/go v1.1.12 // indirect 31 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 32 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 33 | github.com/modern-go/reflect2 v1.0.2 // indirect 34 | github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect 35 | github.com/opencontainers/go-digest v1.0.0 // indirect 36 | github.com/opencontainers/image-spec v1.1.0 // indirect 37 | github.com/protocolbuffers/txtpbfmt v0.0.0-20240116145035-ef3ab179eed6 // indirect 38 | golang.org/x/net v0.21.0 // indirect 39 | golang.org/x/text v0.14.0 // indirect 40 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 41 | gopkg.in/inf.v0 v0.9.1 // indirect 42 | gopkg.in/yaml.v2 v2.4.0 // indirect 43 | gopkg.in/yaml.v3 v3.0.1 // indirect 44 | k8s.io/klog/v2 v2.120.1 // indirect 45 | k8s.io/utils v0.0.0-20240102154912-e7106e64919e // indirect 46 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect 47 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect 48 | ) 49 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/auth/auth.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package auth provides access to user-provided authentication credentials. 6 | package auth 7 | 8 | import "net/http" 9 | 10 | // AddCredentials fills in the user's credentials for req, if any. 11 | // The return value reports whether any matching credentials were found. 12 | func AddCredentials(req *http.Request) (added bool) { 13 | host := req.Host 14 | if host == "" { 15 | host = req.URL.Hostname() 16 | } 17 | 18 | // TODO(golang.org/issue/26232): Support arbitrary user-provided credentials. 19 | netrcOnce.Do(readNetrc) 20 | for _, l := range netrc { 21 | if l.machine == host { 22 | req.SetBasicAuth(l.login, l.password) 23 | return true 24 | } 25 | } 26 | 27 | return false 28 | } 29 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/auth/netrc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package auth 6 | 7 | import ( 8 | "os" 9 | "path/filepath" 10 | "runtime" 11 | "strings" 12 | "sync" 13 | ) 14 | 15 | type netrcLine struct { 16 | machine string 17 | login string 18 | password string 19 | } 20 | 21 | var ( 22 | netrcOnce sync.Once 23 | netrc []netrcLine 24 | netrcErr error 25 | ) 26 | 27 | func parseNetrc(data string) []netrcLine { 28 | // See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html 29 | // for documentation on the .netrc format. 30 | var nrc []netrcLine 31 | var l netrcLine 32 | inMacro := false 33 | for _, line := range strings.Split(data, "\n") { 34 | if inMacro { 35 | if line == "" { 36 | inMacro = false 37 | } 38 | continue 39 | } 40 | 41 | f := strings.Fields(line) 42 | i := 0 43 | for ; i < len(f)-1; i += 2 { 44 | // Reset at each "machine" token. 45 | // “The auto-login process searches the .netrc file for a machine token 46 | // that matches […]. Once a match is made, the subsequent .netrc tokens 47 | // are processed, stopping when the end of file is reached or another 48 | // machine or a default token is encountered.” 49 | switch f[i] { 50 | case "machine": 51 | l = netrcLine{machine: f[i+1]} 52 | case "default": 53 | break 54 | case "login": 55 | l.login = f[i+1] 56 | case "password": 57 | l.password = f[i+1] 58 | case "macdef": 59 | // “A macro is defined with the specified name; its contents begin with 60 | // the next .netrc line and continue until a null line (consecutive 61 | // new-line characters) is encountered.” 62 | inMacro = true 63 | } 64 | if l.machine != "" && l.login != "" && l.password != "" { 65 | nrc = append(nrc, l) 66 | l = netrcLine{} 67 | } 68 | } 69 | 70 | if i < len(f) && f[i] == "default" { 71 | // “There can be only one default token, and it must be after all machine tokens.” 72 | break 73 | } 74 | } 75 | 76 | return nrc 77 | } 78 | 79 | func netrcPath() (string, error) { 80 | if env := os.Getenv("NETRC"); env != "" { 81 | return env, nil 82 | } 83 | dir, err := os.UserHomeDir() 84 | if err != nil { 85 | return "", err 86 | } 87 | base := ".netrc" 88 | if runtime.GOOS == "windows" { 89 | base = "_netrc" 90 | } 91 | return filepath.Join(dir, base), nil 92 | } 93 | 94 | func readNetrc() { 95 | path, err := netrcPath() 96 | if err != nil { 97 | netrcErr = err 98 | return 99 | } 100 | 101 | data, err := os.ReadFile(path) 102 | if err != nil { 103 | if !os.IsNotExist(err) { 104 | netrcErr = err 105 | } 106 | return 107 | } 108 | 109 | netrc = parseNetrc(string(data)) 110 | } 111 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/base/env.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package base 6 | 7 | import ( 8 | "fmt" 9 | "github.com/octohelm/cuemod/internal/cmd/go/internals/cfg" 10 | "os" 11 | "path/filepath" 12 | "runtime" 13 | ) 14 | 15 | // AppendPWD returns the result of appending PWD=dir to the environment base. 16 | // 17 | // The resulting environment makes os.Getwd more efficient for a subprocess 18 | // running in dir, and also improves the accuracy of paths relative to dir 19 | // if one or more elements of dir is a symlink. 20 | func AppendPWD(base []string, dir string) []string { 21 | // POSIX requires PWD to be absolute. 22 | // Internally we only use absolute paths, so dir should already be absolute. 23 | if !filepath.IsAbs(dir) { 24 | panic(fmt.Sprintf("AppendPWD with relative path %q", dir)) 25 | } 26 | return append(base, "PWD="+dir) 27 | } 28 | 29 | // AppendPATH returns the result of appending PATH=$GOROOT/bin:$PATH 30 | // (or the platform equivalent) to the environment base. 31 | func AppendPATH(base []string) []string { 32 | if cfg.GOROOTbin == "" { 33 | return base 34 | } 35 | 36 | pathVar := "PATH" 37 | if runtime.GOOS == "plan9" { 38 | pathVar = "path" 39 | } 40 | 41 | path := os.Getenv(pathVar) 42 | if path == "" { 43 | return append(base, pathVar+"="+cfg.GOROOTbin) 44 | } 45 | return append(base, pathVar+"="+cfg.GOROOTbin+string(os.PathListSeparator)+path) 46 | } 47 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/base/flag.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package base 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | 11 | "github.com/octohelm/cuemod/internal/cmd/go/internals/cfg" 12 | "github.com/octohelm/cuemod/internal/cmd/go/internals/fsys" 13 | "github.com/octohelm/cuemod/internal/cmd/internals/quoted" 14 | ) 15 | 16 | // A StringsFlag is a command-line flag that interprets its argument 17 | // as a space-separated list of possibly-quoted strings. 18 | type StringsFlag []string 19 | 20 | func (v *StringsFlag) Set(s string) error { 21 | var err error 22 | *v, err = quoted.Split(s) 23 | if *v == nil { 24 | *v = []string{} 25 | } 26 | return err 27 | } 28 | 29 | func (v *StringsFlag) String() string { 30 | return "" 31 | } 32 | 33 | // explicitStringFlag is like a regular string flag, but it also tracks whether 34 | // the string was set explicitly to a non-empty value. 35 | type explicitStringFlag struct { 36 | value *string 37 | explicit *bool 38 | } 39 | 40 | func (f explicitStringFlag) String() string { 41 | if f.value == nil { 42 | return "" 43 | } 44 | return *f.value 45 | } 46 | 47 | func (f explicitStringFlag) Set(v string) error { 48 | *f.value = v 49 | if v != "" { 50 | *f.explicit = true 51 | } 52 | return nil 53 | } 54 | 55 | // AddBuildFlagsNX adds the -n and -x build flags to the flag set. 56 | func AddBuildFlagsNX(flags *flag.FlagSet) { 57 | flags.BoolVar(&cfg.BuildN, "n", false, "") 58 | flags.BoolVar(&cfg.BuildX, "x", false, "") 59 | } 60 | 61 | // AddChdirFlag adds the -C flag to the flag set. 62 | func AddChdirFlag(flags *flag.FlagSet) { 63 | // The usage message is never printed, but it's used in chdir_test.go 64 | // to identify that the -C flag is from AddChdirFlag. 65 | flags.Func("C", "AddChdirFlag", ChdirFlag) 66 | } 67 | 68 | // AddModFlag adds the -mod build flag to the flag set. 69 | func AddModFlag(flags *flag.FlagSet) { 70 | flags.Var(explicitStringFlag{value: &cfg.BuildMod, explicit: &cfg.BuildModExplicit}, "mod", "") 71 | } 72 | 73 | // AddModCommonFlags adds the module-related flags common to build commands 74 | // and 'go mod' subcommands. 75 | func AddModCommonFlags(flags *flag.FlagSet) { 76 | flags.BoolVar(&cfg.ModCacheRW, "modcacherw", false, "") 77 | flags.StringVar(&cfg.ModFile, "modfile", "", "") 78 | flags.StringVar(&fsys.OverlayFile, "overlay", "", "") 79 | } 80 | 81 | func ChdirFlag(s string) error { 82 | // main handles -C by removing it from the command line. 83 | // If we see one during flag parsing, that's an error. 84 | return fmt.Errorf("-C flag must be first flag on command line") 85 | } 86 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/base/limit.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package base 6 | 7 | import ( 8 | "fmt" 9 | "github.com/octohelm/cuemod/internal/internals/godebug" 10 | "runtime" 11 | "strconv" 12 | "sync" 13 | ) 14 | 15 | var NetLimitGodebug = godebug.New("#cmdgonetlimit") 16 | 17 | // NetLimit returns the limit on concurrent network operations 18 | // configured by GODEBUG=cmdgonetlimit, if any. 19 | // 20 | // A limit of 0 (indicated by 0, true) means that network operations should not 21 | // be allowed. 22 | func NetLimit() (int, bool) { 23 | netLimitOnce.Do(func() { 24 | s := NetLimitGodebug.Value() 25 | if s == "" { 26 | return 27 | } 28 | 29 | n, err := strconv.Atoi(s) 30 | if err != nil { 31 | Fatalf("invalid %s: %v", NetLimitGodebug.Name(), err) 32 | } 33 | if n < 0 { 34 | // Treat negative values as unlimited. 35 | return 36 | } 37 | netLimitSem = make(chan struct{}, n) 38 | }) 39 | 40 | return cap(netLimitSem), netLimitSem != nil 41 | } 42 | 43 | // AcquireNet acquires a semaphore token for a network operation. 44 | func AcquireNet() (release func(), err error) { 45 | hasToken := false 46 | if n, ok := NetLimit(); ok { 47 | if n == 0 { 48 | return nil, fmt.Errorf("network disabled by %v=%v", NetLimitGodebug.Name(), NetLimitGodebug.Value()) 49 | } 50 | netLimitSem <- struct{}{} 51 | hasToken = true 52 | } 53 | 54 | checker := new(netTokenChecker) 55 | runtime.SetFinalizer(checker, (*netTokenChecker).panicUnreleased) 56 | 57 | return func() { 58 | if checker.released { 59 | panic("internal error: net token released twice") 60 | } 61 | checker.released = true 62 | if hasToken { 63 | <-netLimitSem 64 | } 65 | runtime.SetFinalizer(checker, nil) 66 | }, nil 67 | } 68 | 69 | var ( 70 | netLimitOnce sync.Once 71 | netLimitSem chan struct{} 72 | ) 73 | 74 | type netTokenChecker struct { 75 | released bool 76 | // We want to use a finalizer to check that all acquired tokens are returned, 77 | // so we arbitrarily pad the tokens with a string to defeat the runtime's 78 | // “tiny allocator”. 79 | unusedAvoidTinyAllocator string 80 | } 81 | 82 | func (c *netTokenChecker) panicUnreleased() { 83 | panic("internal error: net token acquired but not released") 84 | } 85 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/base/path.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package base 6 | 7 | import ( 8 | "os" 9 | "path/filepath" 10 | "runtime" 11 | "strings" 12 | "sync" 13 | ) 14 | 15 | var cwd string 16 | var cwdOnce sync.Once 17 | 18 | // UncachedCwd returns the current working directory. 19 | // Most callers should use Cwd, which caches the result for future use. 20 | // UncachedCwd is appropriate to call early in program startup before flag parsing, 21 | // because the -C flag may change the current directory. 22 | func UncachedCwd() string { 23 | wd, err := os.Getwd() 24 | if err != nil { 25 | Fatalf("cannot determine current directory: %v", err) 26 | } 27 | return wd 28 | } 29 | 30 | // Cwd returns the current working directory at the time of the first call. 31 | func Cwd() string { 32 | cwdOnce.Do(func() { 33 | cwd = UncachedCwd() 34 | }) 35 | return cwd 36 | } 37 | 38 | // ShortPath returns an absolute or relative name for path, whatever is shorter. 39 | func ShortPath(path string) string { 40 | if rel, err := filepath.Rel(Cwd(), path); err == nil && len(rel) < len(path) { 41 | return rel 42 | } 43 | return path 44 | } 45 | 46 | // RelPaths returns a copy of paths with absolute paths 47 | // made relative to the current directory if they would be shorter. 48 | func RelPaths(paths []string) []string { 49 | var out []string 50 | for _, p := range paths { 51 | rel, err := filepath.Rel(Cwd(), p) 52 | if err == nil && len(rel) < len(p) { 53 | p = rel 54 | } 55 | out = append(out, p) 56 | } 57 | return out 58 | } 59 | 60 | // IsTestFile reports whether the source file is a set of tests and should therefore 61 | // be excluded from coverage analysis. 62 | func IsTestFile(file string) bool { 63 | // We don't cover tests, only the code they test. 64 | return strings.HasSuffix(file, "_test.go") 65 | } 66 | 67 | // IsNull reports whether the path is a common name for the null device. 68 | // It returns true for /dev/null on Unix, or NUL (case-insensitive) on Windows. 69 | func IsNull(path string) bool { 70 | if path == os.DevNull { 71 | return true 72 | } 73 | if runtime.GOOS == "windows" { 74 | if strings.EqualFold(path, "NUL") { 75 | return true 76 | } 77 | } 78 | return false 79 | } 80 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/base/signal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package base 6 | 7 | import ( 8 | "os" 9 | "os/signal" 10 | "sync" 11 | ) 12 | 13 | // Interrupted is closed when the go command receives an interrupt signal. 14 | var Interrupted = make(chan struct{}) 15 | 16 | // processSignals setups signal handler. 17 | func processSignals() { 18 | sig := make(chan os.Signal, 1) 19 | signal.Notify(sig, signalsToIgnore...) 20 | go func() { 21 | <-sig 22 | close(Interrupted) 23 | }() 24 | } 25 | 26 | var onceProcessSignals sync.Once 27 | 28 | // StartSigHandlers starts the signal handlers. 29 | func StartSigHandlers() { 30 | onceProcessSignals.Do(processSignals) 31 | } 32 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/base/signal_notunix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build plan9 || windows 6 | 7 | package base 8 | 9 | import ( 10 | "os" 11 | ) 12 | 13 | var signalsToIgnore = []os.Signal{os.Interrupt} 14 | 15 | // SignalTrace is the signal to send to make a Go program 16 | // crash with a stack trace (no such signal in this case). 17 | var SignalTrace os.Signal = nil 18 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/base/signal_unix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build unix || js || wasip1 6 | 7 | package base 8 | 9 | import ( 10 | "os" 11 | "syscall" 12 | ) 13 | 14 | var signalsToIgnore = []os.Signal{os.Interrupt, syscall.SIGQUIT} 15 | 16 | // SignalTrace is the signal to send to make a Go program 17 | // crash with a stack trace. 18 | var SignalTrace os.Signal = syscall.SIGQUIT 19 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/base/tool.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package base 6 | 7 | import ( 8 | "fmt" 9 | "go/build" 10 | "os" 11 | "path/filepath" 12 | 13 | "github.com/octohelm/cuemod/internal/cmd/go/internals/cfg" 14 | "github.com/octohelm/cuemod/internal/cmd/go/internals/par" 15 | ) 16 | 17 | // Tool returns the path to the named tool (for example, "vet"). 18 | // If the tool cannot be found, Tool exits the process. 19 | func Tool(toolName string) string { 20 | toolPath, err := ToolPath(toolName) 21 | if err != nil && len(cfg.BuildToolexec) == 0 { 22 | // Give a nice message if there is no tool with that name. 23 | fmt.Fprintf(os.Stderr, "go: no such tool %q\n", toolName) 24 | SetExitStatus(2) 25 | Exit() 26 | } 27 | return toolPath 28 | } 29 | 30 | // Tool returns the path at which we expect to find the named tool 31 | // (for example, "vet"), and the error (if any) from statting that path. 32 | func ToolPath(toolName string) (string, error) { 33 | toolPath := filepath.Join(build.ToolDir, toolName) + cfg.ToolExeSuffix() 34 | err := toolStatCache.Do(toolPath, func() error { 35 | _, err := os.Stat(toolPath) 36 | return err 37 | }) 38 | return toolPath, err 39 | } 40 | 41 | var toolStatCache par.Cache[string, error] 42 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/cache/default.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cache 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "path/filepath" 11 | "sync" 12 | 13 | "github.com/octohelm/cuemod/internal/cmd/go/internals/base" 14 | "github.com/octohelm/cuemod/internal/cmd/go/internals/cfg" 15 | "github.com/octohelm/cuemod/internal/internals/goexperiment" 16 | ) 17 | 18 | // Default returns the default cache to use. 19 | // It never returns nil. 20 | func Default() Cache { 21 | defaultOnce.Do(initDefaultCache) 22 | return defaultCache 23 | } 24 | 25 | var ( 26 | defaultOnce sync.Once 27 | defaultCache Cache 28 | ) 29 | 30 | // cacheREADME is a message stored in a README in the cache directory. 31 | // Because the cache lives outside the normal Go trees, we leave the 32 | // README as a courtesy to explain where it came from. 33 | const cacheREADME = `This directory holds cached build artifacts from the Go build system. 34 | Run "go clean -cache" if the directory is getting too large. 35 | Run "go clean -fuzzcache" to delete the fuzz cache. 36 | See golang.org to learn more about Go. 37 | ` 38 | 39 | // initDefaultCache does the work of finding the default cache 40 | // the first time Default is called. 41 | func initDefaultCache() { 42 | dir := DefaultDir() 43 | if dir == "off" { 44 | if defaultDirErr != nil { 45 | base.Fatalf("build cache is required, but could not be located: %v", defaultDirErr) 46 | } 47 | base.Fatalf("build cache is disabled by GOCACHE=off, but required as of Go 1.12") 48 | } 49 | if err := os.MkdirAll(dir, 0777); err != nil { 50 | base.Fatalf("failed to initialize build cache at %s: %s\n", dir, err) 51 | } 52 | if _, err := os.Stat(filepath.Join(dir, "README")); err != nil { 53 | // Best effort. 54 | os.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666) 55 | } 56 | 57 | diskCache, err := Open(dir) 58 | if err != nil { 59 | base.Fatalf("failed to initialize build cache at %s: %s\n", dir, err) 60 | } 61 | 62 | if v := cfg.Getenv("GOCACHEPROG"); v != "" && goexperiment.CacheProg { 63 | defaultCache = startCacheProg(v, diskCache) 64 | } else { 65 | defaultCache = diskCache 66 | } 67 | } 68 | 69 | var ( 70 | defaultDirOnce sync.Once 71 | defaultDir string 72 | defaultDirErr error 73 | ) 74 | 75 | // DefaultDir returns the effective GOCACHE setting. 76 | // It returns "off" if the cache is disabled. 77 | func DefaultDir() string { 78 | // Save the result of the first call to DefaultDir for later use in 79 | // initDefaultCache. cmd/go/main.go explicitly sets GOCACHE so that 80 | // subprocesses will inherit it, but that means initDefaultCache can't 81 | // otherwise distinguish between an explicit "off" and a UserCacheDir error. 82 | 83 | defaultDirOnce.Do(func() { 84 | defaultDir = cfg.Getenv("GOCACHE") 85 | if filepath.IsAbs(defaultDir) || defaultDir == "off" { 86 | return 87 | } 88 | if defaultDir != "" { 89 | defaultDir = "off" 90 | defaultDirErr = fmt.Errorf("GOCACHE is not an absolute path") 91 | return 92 | } 93 | 94 | // Compute default location. 95 | dir, err := os.UserCacheDir() 96 | if err != nil { 97 | defaultDir = "off" 98 | defaultDirErr = fmt.Errorf("GOCACHE is not defined and %v", err) 99 | return 100 | } 101 | defaultDir = filepath.Join(dir, "go-build") 102 | }) 103 | 104 | return defaultDir 105 | } 106 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/cfg/lookpath.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cfg 6 | 7 | import ( 8 | "github.com/octohelm/cuemod/internal/cmd/go/internals/par" 9 | "os/exec" 10 | ) 11 | 12 | var lookPathCache par.ErrCache[string, string] 13 | 14 | // LookPath wraps exec.LookPath and caches the result 15 | // which can be called by multiple Goroutines at the same time. 16 | func LookPath(file string) (path string, err error) { 17 | return lookPathCache.Do(file, 18 | func() (string, error) { 19 | return exec.LookPath(file) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/cfg/zdefaultcc.go: -------------------------------------------------------------------------------- 1 | // Code generated by go tool dist; DO NOT EDIT. 2 | 3 | package cfg 4 | 5 | const DefaultPkgConfig = `pkg-config` 6 | 7 | func DefaultCC(goos, goarch string) string { 8 | switch goos + `/` + goarch { 9 | } 10 | return "cc" 11 | } 12 | func DefaultCXX(goos, goarch string) string { 13 | switch goos + `/` + goarch { 14 | } 15 | return "c++" 16 | } 17 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/gover/gomod.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gover 6 | 7 | import ( 8 | "bytes" 9 | "strings" 10 | ) 11 | 12 | var nl = []byte("\n") 13 | 14 | // GoModLookup takes go.mod or go.work content, 15 | // finds the first line in the file starting with the given key, 16 | // and returns the value associated with that key. 17 | // 18 | // Lookup should only be used with non-factored verbs 19 | // such as "go" and "toolchain", usually to find versions 20 | // or version-like strings. 21 | func GoModLookup(gomod []byte, key string) string { 22 | for len(gomod) > 0 { 23 | var line []byte 24 | line, gomod, _ = bytes.Cut(gomod, nl) 25 | line = bytes.TrimSpace(line) 26 | if v, ok := parseKey(line, key); ok { 27 | return v 28 | } 29 | } 30 | return "" 31 | } 32 | 33 | func parseKey(line []byte, key string) (string, bool) { 34 | if !strings.HasPrefix(string(line), key) { 35 | return "", false 36 | } 37 | s := strings.TrimPrefix(string(line), key) 38 | if len(s) == 0 || (s[0] != ' ' && s[0] != '\t') { 39 | return "", false 40 | } 41 | s, _, _ = strings.Cut(s, "//") // strip comments 42 | return strings.TrimSpace(s), true 43 | } 44 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/gover/gover.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package gover implements support for Go toolchain versions like 1.21.0 and 1.21rc1. 6 | // (For historical reasons, Go does not use semver for its toolchains.) 7 | // This package provides the same basic analysis that golang.org/x/mod/semver does for semver. 8 | // It also provides some helpers for extracting versions from go.mod files 9 | // and for dealing with module.Versions that may use Go versions or semver 10 | // depending on the module path. 11 | package gover 12 | 13 | import ( 14 | "github.com/octohelm/cuemod/internal/internals/gover" 15 | ) 16 | 17 | // Compare returns -1, 0, or +1 depending on whether 18 | // x < y, x == y, or x > y, interpreted as toolchain versions. 19 | // The versions x and y must not begin with a "go" prefix: just "1.21" not "go1.21". 20 | // Malformed versions compare less than well-formed versions and equal to each other. 21 | // The language version "1.21" compares less than the release candidate and eventual releases "1.21rc1" and "1.21.0". 22 | func Compare(x, y string) int { 23 | return gover.Compare(x, y) 24 | } 25 | 26 | // Max returns the maximum of x and y interpreted as toolchain versions, 27 | // compared using Compare. 28 | // If x and y compare equal, Max returns x. 29 | func Max(x, y string) string { 30 | return gover.Max(x, y) 31 | } 32 | 33 | // IsLang reports whether v denotes the overall Go language version 34 | // and not a specific release. Starting with the Go 1.21 release, "1.x" denotes 35 | // the overall language version; the first release is "1.x.0". 36 | // The distinction is important because the relative ordering is 37 | // 38 | // 1.21 < 1.21rc1 < 1.21.0 39 | // 40 | // meaning that Go 1.21rc1 and Go 1.21.0 will both handle go.mod files that 41 | // say "go 1.21", but Go 1.21rc1 will not handle files that say "go 1.21.0". 42 | func IsLang(x string) bool { 43 | return gover.IsLang(x) 44 | } 45 | 46 | // Lang returns the Go language version. For example, Lang("1.2.3") == "1.2". 47 | func Lang(x string) string { 48 | return gover.Lang(x) 49 | } 50 | 51 | // IsPrerelease reports whether v denotes a Go prerelease version. 52 | func IsPrerelease(x string) bool { 53 | return gover.Parse(x).Kind != "" 54 | } 55 | 56 | // Prev returns the Go major release immediately preceding v, 57 | // or v itself if v is the first Go major release (1.0) or not a supported 58 | // Go version. 59 | // 60 | // Examples: 61 | // 62 | // Prev("1.2") = "1.1" 63 | // Prev("1.3rc4") = "1.2" 64 | func Prev(x string) string { 65 | v := gover.Parse(x) 66 | if gover.CmpInt(v.Minor, "1") <= 0 { 67 | return v.Major 68 | } 69 | return v.Major + "." + gover.DecInt(v.Minor) 70 | } 71 | 72 | // IsValid reports whether the version x is valid. 73 | func IsValid(x string) bool { 74 | return gover.IsValid(x) 75 | } 76 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/gover/local.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gover 6 | 7 | import ( 8 | "github.com/octohelm/cuemod/internal/internals/goversion" 9 | "runtime" 10 | "strconv" 11 | ) 12 | 13 | // TestVersion is initialized in the go command test binary 14 | // to be $TESTGO_VERSION, to allow tests to override the 15 | // go command's idea of its own version as returned by Local. 16 | var TestVersion string 17 | 18 | // Local returns the local Go version, the one implemented by this go command. 19 | func Local() string { 20 | v, _ := local() 21 | return v 22 | } 23 | 24 | // LocalToolchain returns the local toolchain name, the one implemented by this go command. 25 | func LocalToolchain() string { 26 | _, t := local() 27 | return t 28 | } 29 | 30 | func local() (goVers, toolVers string) { 31 | toolVers = runtime.Version() 32 | if TestVersion != "" { 33 | toolVers = TestVersion 34 | } 35 | goVers = FromToolchain(toolVers) 36 | if goVers == "" { 37 | // Development branch. Use "Dev" version with just 1.N, no rc1 or .0 suffix. 38 | goVers = "1." + strconv.Itoa(goversion.Version) 39 | toolVers = "go" + goVers 40 | } 41 | return goVers, toolVers 42 | } 43 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/gover/toolchain.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gover 6 | 7 | import ( 8 | "context" 9 | "errors" 10 | "fmt" 11 | "github.com/octohelm/cuemod/internal/cmd/go/internals/base" 12 | "strings" 13 | ) 14 | 15 | // FromToolchain returns the Go version for the named toolchain, 16 | // derived from the name itself (not by running the toolchain). 17 | // A toolchain is named "goVERSION". 18 | // A suffix after the VERSION introduced by a -, space, or tab is removed. 19 | // Examples: 20 | // 21 | // FromToolchain("go1.2.3") == "1.2.3" 22 | // FromToolchain("go1.2.3-bigcorp") == "1.2.3" 23 | // FromToolchain("invalid") == "" 24 | func FromToolchain(name string) string { 25 | if strings.ContainsAny(name, "\\/") { 26 | // The suffix must not include a path separator, since that would cause 27 | // exec.LookPath to resolve it from a relative directory instead of from 28 | // $PATH. 29 | return "" 30 | } 31 | 32 | var v string 33 | if strings.HasPrefix(name, "go") { 34 | v = name[2:] 35 | } else { 36 | return "" 37 | } 38 | // Some builds use custom suffixes; strip them. 39 | if i := strings.IndexAny(v, " \t-"); i >= 0 { 40 | v = v[:i] 41 | } 42 | if !IsValid(v) { 43 | return "" 44 | } 45 | return v 46 | } 47 | 48 | func maybeToolchainVersion(name string) string { 49 | if IsValid(name) { 50 | return name 51 | } 52 | return FromToolchain(name) 53 | } 54 | 55 | // ToolchainMax returns the maximum of x and y interpreted as toolchain names, 56 | // compared using Compare(FromToolchain(x), FromToolchain(y)). 57 | // If x and y compare equal, Max returns x. 58 | func ToolchainMax(x, y string) string { 59 | if Compare(FromToolchain(x), FromToolchain(y)) < 0 { 60 | return y 61 | } 62 | return x 63 | } 64 | 65 | // Startup records the information that went into the startup-time version switch. 66 | // It is initialized by switchGoToolchain. 67 | var Startup struct { 68 | GOTOOLCHAIN string // $GOTOOLCHAIN setting 69 | AutoFile string // go.mod or go.work file consulted 70 | AutoGoVersion string // go line found in file 71 | AutoToolchain string // toolchain line found in file 72 | } 73 | 74 | // A TooNewError explains that a module is too new for this version of Go. 75 | type TooNewError struct { 76 | What string 77 | GoVersion string 78 | Toolchain string // for callers if they want to use it, but not printed 79 | } 80 | 81 | func (e *TooNewError) Error() string { 82 | var explain string 83 | if Startup.GOTOOLCHAIN != "" && Startup.GOTOOLCHAIN != "auto" { 84 | explain = "; GOTOOLCHAIN=" + Startup.GOTOOLCHAIN 85 | } 86 | if Startup.AutoFile != "" && (Startup.AutoGoVersion != "" || Startup.AutoToolchain != "") { 87 | explain += fmt.Sprintf("; %s sets ", base.ShortPath(Startup.AutoFile)) 88 | if Startup.AutoToolchain != "" { 89 | explain += "toolchain " + Startup.AutoToolchain 90 | } else { 91 | explain += "go " + Startup.AutoGoVersion 92 | } 93 | } 94 | return fmt.Sprintf("%v requires go >= %v (running go %v%v)", e.What, e.GoVersion, Local(), explain) 95 | } 96 | 97 | var ErrTooNew = errors.New("module too new") 98 | 99 | func (e *TooNewError) Is(err error) bool { 100 | return err == ErrTooNew 101 | } 102 | 103 | // A Switcher provides the ability to switch to a new toolchain in response to TooNewErrors. 104 | // See [cmd/go/internal/toolchain.Switcher] for documentation. 105 | type Switcher interface { 106 | Error(err error) 107 | Switch(ctx context.Context) 108 | } 109 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/gover/version.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gover 6 | 7 | import "golang.org/x/mod/modfile" 8 | 9 | const ( 10 | // narrowAllVersion is the Go version at which the 11 | // module-module "all" pattern no longer closes over the dependencies of 12 | // tests outside of the main module. 13 | NarrowAllVersion = "1.16" 14 | 15 | // DefaultGoModVersion is the Go version to assume for go.mod files 16 | // that do not declare a Go version. The go command has been 17 | // writing go versions to modules since Go 1.12, so a go.mod 18 | // without a version is either very old or recently hand-written. 19 | // Since we can't tell which, we have to assume it's very old. 20 | // The semantics of the go.mod changed at Go 1.17 to support 21 | // graph pruning. If see a go.mod without a go line, we have to 22 | // assume Go 1.16 so that we interpret the requirements correctly. 23 | // Note that this default must stay at Go 1.16; it cannot be moved forward. 24 | DefaultGoModVersion = "1.16" 25 | 26 | // DefaultGoWorkVersion is the Go version to assume for go.work files 27 | // that do not declare a Go version. Workspaces were added in Go 1.18, 28 | // so use that. 29 | DefaultGoWorkVersion = "1.18" 30 | 31 | // ExplicitIndirectVersion is the Go version at which a 32 | // module's go.mod file is expected to list explicit requirements on every 33 | // module that provides any package transitively imported by that module. 34 | // 35 | // Other indirect dependencies of such a module can be safely pruned out of 36 | // the module graph; see https://golang.org/ref/mod#graph-pruning. 37 | ExplicitIndirectVersion = "1.17" 38 | 39 | // separateIndirectVersion is the Go version at which 40 | // "// indirect" dependencies are added in a block separate from the direct 41 | // ones. See https://golang.org/issue/45965. 42 | SeparateIndirectVersion = "1.17" 43 | 44 | // tidyGoModSumVersion is the Go version at which 45 | // 'go mod tidy' preserves go.mod checksums needed to build test dependencies 46 | // of packages in "all", so that 'go test all' can be run without checksum 47 | // errors. 48 | // See https://go.dev/issue/56222. 49 | TidyGoModSumVersion = "1.21" 50 | 51 | // goStrictVersion is the Go version at which the Go versions 52 | // became "strict" in the sense that, restricted to modules at this version 53 | // or later, every module must have a go version line ≥ all its dependencies. 54 | // It is also the version after which "too new" a version is considered a fatal error. 55 | GoStrictVersion = "1.21" 56 | ) 57 | 58 | // FromGoMod returns the go version from the go.mod file. 59 | // It returns DefaultGoModVersion if the go.mod file does not contain a go line or if mf is nil. 60 | func FromGoMod(mf *modfile.File) string { 61 | if mf == nil || mf.Go == nil { 62 | return DefaultGoModVersion 63 | } 64 | return mf.Go.Version 65 | } 66 | 67 | // FromGoWork returns the go version from the go.mod file. 68 | // It returns DefaultGoWorkVersion if the go.mod file does not contain a go line or if wf is nil. 69 | func FromGoWork(wf *modfile.WorkFile) string { 70 | if wf == nil || wf.Go == nil { 71 | return DefaultGoWorkVersion 72 | } 73 | return wf.Go.Version 74 | } 75 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/imports/scan.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package imports 6 | 7 | import ( 8 | "fmt" 9 | "io/fs" 10 | "path/filepath" 11 | "sort" 12 | "strconv" 13 | "strings" 14 | 15 | "github.com/octohelm/cuemod/internal/cmd/go/internals/fsys" 16 | ) 17 | 18 | func ScanDir(dir string, tags map[string]bool) ([]string, []string, error) { 19 | infos, err := fsys.ReadDir(dir) 20 | if err != nil { 21 | return nil, nil, err 22 | } 23 | var files []string 24 | for _, info := range infos { 25 | name := info.Name() 26 | 27 | // If the directory entry is a symlink, stat it to obtain the info for the 28 | // link target instead of the link itself. 29 | if info.Mode()&fs.ModeSymlink != 0 { 30 | info, err = fsys.Stat(filepath.Join(dir, name)) 31 | if err != nil { 32 | continue // Ignore broken symlinks. 33 | } 34 | } 35 | 36 | if info.Mode().IsRegular() && !strings.HasPrefix(name, "_") && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") && MatchFile(name, tags) { 37 | files = append(files, filepath.Join(dir, name)) 38 | } 39 | } 40 | return scanFiles(files, tags, false) 41 | } 42 | 43 | func ScanFiles(files []string, tags map[string]bool) ([]string, []string, error) { 44 | return scanFiles(files, tags, true) 45 | } 46 | 47 | func scanFiles(files []string, tags map[string]bool, explicitFiles bool) ([]string, []string, error) { 48 | imports := make(map[string]bool) 49 | testImports := make(map[string]bool) 50 | numFiles := 0 51 | Files: 52 | for _, name := range files { 53 | r, err := fsys.Open(name) 54 | if err != nil { 55 | return nil, nil, err 56 | } 57 | var list []string 58 | data, err := ReadImports(r, false, &list) 59 | r.Close() 60 | if err != nil { 61 | return nil, nil, fmt.Errorf("reading %s: %v", name, err) 62 | } 63 | 64 | // import "C" is implicit requirement of cgo tag. 65 | // When listing files on the command line (explicitFiles=true) 66 | // we do not apply build tag filtering but we still do apply 67 | // cgo filtering, so no explicitFiles check here. 68 | // Why? Because we always have, and it's not worth breaking 69 | // that behavior now. 70 | for _, path := range list { 71 | if path == `"C"` && !tags["cgo"] && !tags["*"] { 72 | continue Files 73 | } 74 | } 75 | 76 | if !explicitFiles && !ShouldBuild(data, tags) { 77 | continue 78 | } 79 | numFiles++ 80 | m := imports 81 | if strings.HasSuffix(name, "_test.go") { 82 | m = testImports 83 | } 84 | for _, p := range list { 85 | q, err := strconv.Unquote(p) 86 | if err != nil { 87 | continue 88 | } 89 | m[q] = true 90 | } 91 | } 92 | if numFiles == 0 { 93 | return nil, nil, ErrNoGo 94 | } 95 | return keys(imports), keys(testImports), nil 96 | } 97 | 98 | var ErrNoGo = fmt.Errorf("no Go source files") 99 | 100 | func keys(m map[string]bool) []string { 101 | var list []string 102 | for k := range m { 103 | list = append(list, k) 104 | } 105 | sort.Strings(list) 106 | return list 107 | } 108 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/imports/tags.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package imports 6 | 7 | import ( 8 | "github.com/octohelm/cuemod/internal/cmd/go/internals/cfg" 9 | "sync" 10 | ) 11 | 12 | var ( 13 | tags map[string]bool 14 | tagsOnce sync.Once 15 | ) 16 | 17 | // Tags returns a set of build tags that are true for the target platform. 18 | // It includes GOOS, GOARCH, the compiler, possibly "cgo", 19 | // release tags like "go1.13", and user-specified build tags. 20 | func Tags() map[string]bool { 21 | tagsOnce.Do(func() { 22 | tags = loadTags() 23 | }) 24 | return tags 25 | } 26 | 27 | func loadTags() map[string]bool { 28 | tags := map[string]bool{ 29 | cfg.BuildContext.GOOS: true, 30 | cfg.BuildContext.GOARCH: true, 31 | cfg.BuildContext.Compiler: true, 32 | } 33 | if cfg.BuildContext.CgoEnabled { 34 | tags["cgo"] = true 35 | } 36 | for _, tag := range cfg.BuildContext.BuildTags { 37 | tags[tag] = true 38 | } 39 | for _, tag := range cfg.BuildContext.ToolTags { 40 | tags[tag] = true 41 | } 42 | for _, tag := range cfg.BuildContext.ReleaseTags { 43 | tags[tag] = true 44 | } 45 | return tags 46 | } 47 | 48 | var ( 49 | anyTags map[string]bool 50 | anyTagsOnce sync.Once 51 | ) 52 | 53 | // AnyTags returns a special set of build tags that satisfy nearly all 54 | // build tag expressions. Only "ignore" and malformed build tag requirements 55 | // are considered false. 56 | func AnyTags() map[string]bool { 57 | anyTagsOnce.Do(func() { 58 | anyTags = map[string]bool{"*": true} 59 | }) 60 | return anyTags 61 | } 62 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/lockedfile/internals/filelock/filelock.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package filelock provides a platform-independent API for advisory file 6 | // locking. Calls to functions in this package on platforms that do not support 7 | // advisory locks will return errors for which IsNotSupported returns true. 8 | package filelock 9 | 10 | import ( 11 | "errors" 12 | "io/fs" 13 | ) 14 | 15 | // A File provides the minimal set of methods required to lock an open file. 16 | // File implementations must be usable as map keys. 17 | // The usual implementation is *os.File. 18 | type File interface { 19 | // Name returns the name of the file. 20 | Name() string 21 | 22 | // Fd returns a valid file descriptor. 23 | // (If the File is an *os.File, it must not be closed.) 24 | Fd() uintptr 25 | 26 | // Stat returns the FileInfo structure describing file. 27 | Stat() (fs.FileInfo, error) 28 | } 29 | 30 | // Lock places an advisory write lock on the file, blocking until it can be 31 | // locked. 32 | // 33 | // If Lock returns nil, no other process will be able to place a read or write 34 | // lock on the file until this process exits, closes f, or calls Unlock on it. 35 | // 36 | // If f's descriptor is already read- or write-locked, the behavior of Lock is 37 | // unspecified. 38 | // 39 | // Closing the file may or may not release the lock promptly. Callers should 40 | // ensure that Unlock is always called when Lock succeeds. 41 | func Lock(f File) error { 42 | return lock(f, writeLock) 43 | } 44 | 45 | // RLock places an advisory read lock on the file, blocking until it can be locked. 46 | // 47 | // If RLock returns nil, no other process will be able to place a write lock on 48 | // the file until this process exits, closes f, or calls Unlock on it. 49 | // 50 | // If f is already read- or write-locked, the behavior of RLock is unspecified. 51 | // 52 | // Closing the file may or may not release the lock promptly. Callers should 53 | // ensure that Unlock is always called if RLock succeeds. 54 | func RLock(f File) error { 55 | return lock(f, readLock) 56 | } 57 | 58 | // Unlock removes an advisory lock placed on f by this process. 59 | // 60 | // The caller must not attempt to unlock a file that is not locked. 61 | func Unlock(f File) error { 62 | return unlock(f) 63 | } 64 | 65 | // String returns the name of the function corresponding to lt 66 | // (Lock, RLock, or Unlock). 67 | func (lt lockType) String() string { 68 | switch lt { 69 | case readLock: 70 | return "RLock" 71 | case writeLock: 72 | return "Lock" 73 | default: 74 | return "Unlock" 75 | } 76 | } 77 | 78 | // IsNotSupported returns a boolean indicating whether the error is known to 79 | // report that a function is not supported (possibly for a specific input). 80 | // It is satisfied by errors.ErrUnsupported as well as some syscall errors. 81 | func IsNotSupported(err error) bool { 82 | return errors.Is(err, errors.ErrUnsupported) 83 | } 84 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/lockedfile/internals/filelock/filelock_other.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !unix && !windows 6 | 7 | package filelock 8 | 9 | import ( 10 | "errors" 11 | "io/fs" 12 | ) 13 | 14 | type lockType int8 15 | 16 | const ( 17 | readLock = iota + 1 18 | writeLock 19 | ) 20 | 21 | func lock(f File, lt lockType) error { 22 | return &fs.PathError{ 23 | Op: lt.String(), 24 | Path: f.Name(), 25 | Err: errors.ErrUnsupported, 26 | } 27 | } 28 | 29 | func unlock(f File) error { 30 | return &fs.PathError{ 31 | Op: "Unlock", 32 | Path: f.Name(), 33 | Err: errors.ErrUnsupported, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/lockedfile/internals/filelock/filelock_unix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build darwin || dragonfly || freebsd || illumos || linux || netbsd || openbsd 6 | 7 | package filelock 8 | 9 | import ( 10 | "io/fs" 11 | "syscall" 12 | ) 13 | 14 | type lockType int16 15 | 16 | const ( 17 | readLock lockType = syscall.LOCK_SH 18 | writeLock lockType = syscall.LOCK_EX 19 | ) 20 | 21 | func lock(f File, lt lockType) (err error) { 22 | for { 23 | err = syscall.Flock(int(f.Fd()), int(lt)) 24 | if err != syscall.EINTR { 25 | break 26 | } 27 | } 28 | if err != nil { 29 | return &fs.PathError{ 30 | Op: lt.String(), 31 | Path: f.Name(), 32 | Err: err, 33 | } 34 | } 35 | return nil 36 | } 37 | 38 | func unlock(f File) error { 39 | return lock(f, syscall.LOCK_UN) 40 | } 41 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/lockedfile/internals/filelock/filelock_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build windows 6 | 7 | package filelock 8 | 9 | import ( 10 | "github.com/octohelm/cuemod/internal/internals/syscall/windows" 11 | "io/fs" 12 | "syscall" 13 | ) 14 | 15 | type lockType uint32 16 | 17 | const ( 18 | readLock lockType = 0 19 | writeLock lockType = windows.LOCKFILE_EXCLUSIVE_LOCK 20 | ) 21 | 22 | const ( 23 | reserved = 0 24 | allBytes = ^uint32(0) 25 | ) 26 | 27 | func lock(f File, lt lockType) error { 28 | // Per https://golang.org/issue/19098, “Programs currently expect the Fd 29 | // method to return a handle that uses ordinary synchronous I/O.” 30 | // However, LockFileEx still requires an OVERLAPPED structure, 31 | // which contains the file offset of the beginning of the lock range. 32 | // We want to lock the entire file, so we leave the offset as zero. 33 | ol := new(syscall.Overlapped) 34 | 35 | err := windows.LockFileEx(syscall.Handle(f.Fd()), uint32(lt), reserved, allBytes, allBytes, ol) 36 | if err != nil { 37 | return &fs.PathError{ 38 | Op: lt.String(), 39 | Path: f.Name(), 40 | Err: err, 41 | } 42 | } 43 | return nil 44 | } 45 | 46 | func unlock(f File) error { 47 | ol := new(syscall.Overlapped) 48 | err := windows.UnlockFileEx(syscall.Handle(f.Fd()), reserved, allBytes, allBytes, ol) 49 | if err != nil { 50 | return &fs.PathError{ 51 | Op: "Unlock", 52 | Path: f.Name(), 53 | Err: err, 54 | } 55 | } 56 | return nil 57 | } 58 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/lockedfile/lockedfile_filelock.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !plan9 6 | 7 | package lockedfile 8 | 9 | import ( 10 | "io/fs" 11 | "os" 12 | 13 | "github.com/octohelm/cuemod/internal/cmd/go/internals/lockedfile/internals/filelock" 14 | ) 15 | 16 | func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) { 17 | // On BSD systems, we could add the O_SHLOCK or O_EXLOCK flag to the OpenFile 18 | // call instead of locking separately, but we have to support separate locking 19 | // calls for Linux and Windows anyway, so it's simpler to use that approach 20 | // consistently. 21 | 22 | f, err := os.OpenFile(name, flag&^os.O_TRUNC, perm) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | switch flag & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR) { 28 | case os.O_WRONLY, os.O_RDWR: 29 | err = filelock.Lock(f) 30 | default: 31 | err = filelock.RLock(f) 32 | } 33 | if err != nil { 34 | f.Close() 35 | return nil, err 36 | } 37 | 38 | if flag&os.O_TRUNC == os.O_TRUNC { 39 | if err := f.Truncate(0); err != nil { 40 | // The documentation for os.O_TRUNC says “if possible, truncate file when 41 | // opened”, but doesn't define “possible” (golang.org/issue/28699). 42 | // We'll treat regular files (and symlinks to regular files) as “possible” 43 | // and ignore errors for the rest. 44 | if fi, statErr := f.Stat(); statErr != nil || fi.Mode().IsRegular() { 45 | filelock.Unlock(f) 46 | f.Close() 47 | return nil, err 48 | } 49 | } 50 | } 51 | 52 | return f, nil 53 | } 54 | 55 | func closeFile(f *os.File) error { 56 | // Since locking syscalls operate on file descriptors, we must unlock the file 57 | // while the descriptor is still valid — that is, before the file is closed — 58 | // and avoid unlocking files that are already closed. 59 | err := filelock.Unlock(f) 60 | 61 | if closeErr := f.Close(); err == nil { 62 | err = closeErr 63 | } 64 | return err 65 | } 66 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/lockedfile/lockedfile_plan9.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build plan9 6 | 7 | package lockedfile 8 | 9 | import ( 10 | "io/fs" 11 | "math/rand" 12 | "os" 13 | "strings" 14 | "time" 15 | ) 16 | 17 | // Opening an exclusive-use file returns an error. 18 | // The expected error strings are: 19 | // 20 | // - "open/create -- file is locked" (cwfs, kfs) 21 | // - "exclusive lock" (fossil) 22 | // - "exclusive use file already open" (ramfs) 23 | var lockedErrStrings = [...]string{ 24 | "file is locked", 25 | "exclusive lock", 26 | "exclusive use file already open", 27 | } 28 | 29 | // Even though plan9 doesn't support the Lock/RLock/Unlock functions to 30 | // manipulate already-open files, IsLocked is still meaningful: os.OpenFile 31 | // itself may return errors that indicate that a file with the ModeExclusive bit 32 | // set is already open. 33 | func isLocked(err error) bool { 34 | s := err.Error() 35 | 36 | for _, frag := range lockedErrStrings { 37 | if strings.Contains(s, frag) { 38 | return true 39 | } 40 | } 41 | 42 | return false 43 | } 44 | 45 | func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) { 46 | // Plan 9 uses a mode bit instead of explicit lock/unlock syscalls. 47 | // 48 | // Per http://man.cat-v.org/plan_9/5/stat: “Exclusive use files may be open 49 | // for I/O by only one fid at a time across all clients of the server. If a 50 | // second open is attempted, it draws an error.” 51 | // 52 | // So we can try to open a locked file, but if it fails we're on our own to 53 | // figure out when it becomes available. We'll use exponential backoff with 54 | // some jitter and an arbitrary limit of 500ms. 55 | 56 | // If the file was unpacked or created by some other program, it might not 57 | // have the ModeExclusive bit set. Set it before we call OpenFile, so that we 58 | // can be confident that a successful OpenFile implies exclusive use. 59 | if fi, err := os.Stat(name); err == nil { 60 | if fi.Mode()&fs.ModeExclusive == 0 { 61 | if err := os.Chmod(name, fi.Mode()|fs.ModeExclusive); err != nil { 62 | return nil, err 63 | } 64 | } 65 | } else if !os.IsNotExist(err) { 66 | return nil, err 67 | } 68 | 69 | nextSleep := 1 * time.Millisecond 70 | const maxSleep = 500 * time.Millisecond 71 | for { 72 | f, err := os.OpenFile(name, flag, perm|fs.ModeExclusive) 73 | if err == nil { 74 | return f, nil 75 | } 76 | 77 | if !isLocked(err) { 78 | return nil, err 79 | } 80 | 81 | time.Sleep(nextSleep) 82 | 83 | nextSleep += nextSleep 84 | if nextSleep > maxSleep { 85 | nextSleep = maxSleep 86 | } 87 | // Apply 10% jitter to avoid synchronizing collisions. 88 | nextSleep += time.Duration((0.1*rand.Float64() - 0.05) * float64(nextSleep)) 89 | } 90 | } 91 | 92 | func closeFile(f *os.File) error { 93 | return f.Close() 94 | } 95 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/lockedfile/mutex.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package lockedfile 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "sync" 11 | ) 12 | 13 | // A Mutex provides mutual exclusion within and across processes by locking a 14 | // well-known file. Such a file generally guards some other part of the 15 | // filesystem: for example, a Mutex file in a directory might guard access to 16 | // the entire tree rooted in that directory. 17 | // 18 | // Mutex does not implement sync.Locker: unlike a sync.Mutex, a lockedfile.Mutex 19 | // can fail to lock (e.g. if there is a permission error in the filesystem). 20 | // 21 | // Like a sync.Mutex, a Mutex may be included as a field of a larger struct but 22 | // must not be copied after first use. The Path field must be set before first 23 | // use and must not be change thereafter. 24 | type Mutex struct { 25 | Path string // The path to the well-known lock file. Must be non-empty. 26 | mu sync.Mutex // A redundant mutex. The race detector doesn't know about file locking, so in tests we may need to lock something that it understands. 27 | } 28 | 29 | // MutexAt returns a new Mutex with Path set to the given non-empty path. 30 | func MutexAt(path string) *Mutex { 31 | if path == "" { 32 | panic("lockedfile.MutexAt: path must be non-empty") 33 | } 34 | return &Mutex{Path: path} 35 | } 36 | 37 | func (mu *Mutex) String() string { 38 | return fmt.Sprintf("lockedfile.Mutex(%s)", mu.Path) 39 | } 40 | 41 | // Lock attempts to lock the Mutex. 42 | // 43 | // If successful, Lock returns a non-nil unlock function: it is provided as a 44 | // return-value instead of a separate method to remind the caller to check the 45 | // accompanying error. (See https://golang.org/issue/20803.) 46 | func (mu *Mutex) Lock() (unlock func(), err error) { 47 | if mu.Path == "" { 48 | panic("lockedfile.Mutex: missing Path during Lock") 49 | } 50 | 51 | // We could use either O_RDWR or O_WRONLY here. If we choose O_RDWR and the 52 | // file at mu.Path is write-only, the call to OpenFile will fail with a 53 | // permission error. That's actually what we want: if we add an RLock method 54 | // in the future, it should call OpenFile with O_RDONLY and will require the 55 | // files must be readable, so we should not let the caller make any 56 | // assumptions about Mutex working with write-only files. 57 | f, err := OpenFile(mu.Path, os.O_RDWR|os.O_CREATE, 0666) 58 | if err != nil { 59 | return nil, err 60 | } 61 | mu.mu.Lock() 62 | 63 | return func() { 64 | mu.mu.Unlock() 65 | f.Close() 66 | }, nil 67 | } 68 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/mmap/mmap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This package is a lightly modified version of the mmap code 6 | // in github.com/google/codesearch/index. 7 | 8 | // The mmap package provides an abstraction for memory mapping files 9 | // on different platforms. 10 | package mmap 11 | 12 | import ( 13 | "os" 14 | ) 15 | 16 | // Data is mmap'ed read-only data from a file. 17 | // The backing file is never closed, so Data 18 | // remains valid for the lifetime of the process. 19 | type Data struct { 20 | f *os.File 21 | Data []byte 22 | } 23 | 24 | // Mmap maps the given file into memory. 25 | func Mmap(file string) (Data, error) { 26 | f, err := os.Open(file) 27 | if err != nil { 28 | return Data{}, err 29 | } 30 | return mmapFile(f) 31 | } 32 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/mmap/mmap_other.go: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build (js && wasm) || wasip1 || plan9 6 | 7 | package mmap 8 | 9 | import ( 10 | "io" 11 | "os" 12 | ) 13 | 14 | // mmapFile on other systems doesn't mmap the file. It just reads everything. 15 | func mmapFile(f *os.File) (Data, error) { 16 | b, err := io.ReadAll(f) 17 | if err != nil { 18 | return Data{}, err 19 | } 20 | return Data{f, b}, nil 21 | } 22 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/mmap/mmap_unix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build unix 6 | 7 | package mmap 8 | 9 | import ( 10 | "fmt" 11 | "io/fs" 12 | "os" 13 | "syscall" 14 | ) 15 | 16 | func mmapFile(f *os.File) (Data, error) { 17 | st, err := f.Stat() 18 | if err != nil { 19 | return Data{}, err 20 | } 21 | size := st.Size() 22 | pagesize := int64(os.Getpagesize()) 23 | if int64(int(size+(pagesize-1))) != size+(pagesize-1) { 24 | return Data{}, fmt.Errorf("%s: too large for mmap", f.Name()) 25 | } 26 | n := int(size) 27 | if n == 0 { 28 | return Data{f, nil}, nil 29 | } 30 | mmapLength := int(((size + pagesize - 1) / pagesize) * pagesize) // round up to page size 31 | data, err := syscall.Mmap(int(f.Fd()), 0, mmapLength, syscall.PROT_READ, syscall.MAP_SHARED) 32 | if err != nil { 33 | return Data{}, &fs.PathError{Op: "mmap", Path: f.Name(), Err: err} 34 | } 35 | return Data{f, data[:n]}, nil 36 | } 37 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/mmap/mmap_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package mmap 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "syscall" 11 | "unsafe" 12 | 13 | "github.com/octohelm/cuemod/internal/internals/syscall/windows" 14 | ) 15 | 16 | func mmapFile(f *os.File) (Data, error) { 17 | st, err := f.Stat() 18 | if err != nil { 19 | return Data{}, err 20 | } 21 | size := st.Size() 22 | if size == 0 { 23 | return Data{f, nil}, nil 24 | } 25 | h, err := syscall.CreateFileMapping(syscall.Handle(f.Fd()), nil, syscall.PAGE_READONLY, 0, 0, nil) 26 | if err != nil { 27 | return Data{}, fmt.Errorf("CreateFileMapping %s: %w", f.Name(), err) 28 | } 29 | 30 | addr, err := syscall.MapViewOfFile(h, syscall.FILE_MAP_READ, 0, 0, 0) 31 | if err != nil { 32 | return Data{}, fmt.Errorf("MapViewOfFile %s: %w", f.Name(), err) 33 | } 34 | var info windows.MemoryBasicInformation 35 | err = windows.VirtualQuery(addr, &info, unsafe.Sizeof(info)) 36 | if err != nil { 37 | return Data{}, fmt.Errorf("VirtualQuery %s: %w", f.Name(), err) 38 | } 39 | data := unsafe.Slice((*byte)(unsafe.Pointer(addr)), int(info.RegionSize)) 40 | return Data{f, data}, nil 41 | } 42 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/modfetch/bootstrap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build cmd_go_bootstrap 6 | 7 | package modfetch 8 | 9 | import "golang.org/x/mod/module" 10 | 11 | func useSumDB(mod module.Version) bool { 12 | return false 13 | } 14 | 15 | func lookupSumDB(mod module.Version) (string, []string, error) { 16 | panic("bootstrap") 17 | } 18 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/modfetch/key.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package modfetch 6 | 7 | var knownGOSUMDB = map[string]string{ 8 | "sum.golang.org": "sum.golang.org+033de0ae+Ac4zctda0e5eza+HJyk9SxEdh+s3Ux18htTTAD8OuAn8", 9 | } 10 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/modindex/syslist.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file is a lightly modified copy go/build/syslist_test.go. 6 | 7 | package modindex 8 | 9 | // knownOS is the list of past, present, and future known GOOS values. 10 | // Do not remove from this list, as it is used for filename matching. 11 | // If you add an entry to this list, look at unixOS, below. 12 | var knownOS = map[string]bool{ 13 | "aix": true, 14 | "android": true, 15 | "darwin": true, 16 | "dragonfly": true, 17 | "freebsd": true, 18 | "hurd": true, 19 | "illumos": true, 20 | "ios": true, 21 | "js": true, 22 | "linux": true, 23 | "nacl": true, 24 | "netbsd": true, 25 | "openbsd": true, 26 | "plan9": true, 27 | "solaris": true, 28 | "wasip1": true, 29 | "windows": true, 30 | "zos": true, 31 | } 32 | 33 | // unixOS is the set of GOOS values matched by the "unix" build tag. 34 | // This is not used for filename matching. 35 | // This list also appears in cmd/dist/build.go. 36 | var unixOS = map[string]bool{ 37 | "aix": true, 38 | "android": true, 39 | "darwin": true, 40 | "dragonfly": true, 41 | "freebsd": true, 42 | "hurd": true, 43 | "illumos": true, 44 | "ios": true, 45 | "linux": true, 46 | "netbsd": true, 47 | "openbsd": true, 48 | "solaris": true, 49 | } 50 | 51 | // knownArch is the list of past, present, and future known GOARCH values. 52 | // Do not remove from this list, as it is used for filename matching. 53 | var knownArch = map[string]bool{ 54 | "386": true, 55 | "amd64": true, 56 | "amd64p32": true, 57 | "arm": true, 58 | "armbe": true, 59 | "arm64": true, 60 | "arm64be": true, 61 | "loong64": true, 62 | "mips": true, 63 | "mipsle": true, 64 | "mips64": true, 65 | "mips64le": true, 66 | "mips64p32": true, 67 | "mips64p32le": true, 68 | "ppc": true, 69 | "ppc64": true, 70 | "ppc64le": true, 71 | "riscv": true, 72 | "riscv64": true, 73 | "s390": true, 74 | "s390x": true, 75 | "sparc": true, 76 | "sparc64": true, 77 | "wasm": true, 78 | } 79 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/modinfo/info.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package modinfo 6 | 7 | import ( 8 | "encoding/json" 9 | "github.com/octohelm/cuemod/internal/cmd/go/internals/modfetch/codehost" 10 | "time" 11 | ) 12 | 13 | // Note that these structs are publicly visible (part of go list's API) 14 | // and the fields are documented in the help text in ../list/list.go 15 | 16 | type ModulePublic struct { 17 | Path string `json:",omitempty"` // module path 18 | Version string `json:",omitempty"` // module version 19 | Query string `json:",omitempty"` // version query corresponding to this version 20 | Versions []string `json:",omitempty"` // available module versions 21 | Replace *ModulePublic `json:",omitempty"` // replaced by this module 22 | Time *time.Time `json:",omitempty"` // time version was created 23 | Update *ModulePublic `json:",omitempty"` // available update (with -u) 24 | Main bool `json:",omitempty"` // is this the main module? 25 | Indirect bool `json:",omitempty"` // module is only indirectly needed by main module 26 | Dir string `json:",omitempty"` // directory holding local copy of files, if any 27 | GoMod string `json:",omitempty"` // path to go.mod file describing module, if any 28 | GoVersion string `json:",omitempty"` // go version used in module 29 | Retracted []string `json:",omitempty"` // retraction information, if any (with -retracted or -u) 30 | Deprecated string `json:",omitempty"` // deprecation message, if any (with -u) 31 | Error *ModuleError `json:",omitempty"` // error loading module 32 | 33 | Origin *codehost.Origin `json:",omitempty"` // provenance of module 34 | Reuse bool `json:",omitempty"` // reuse of old module info is safe 35 | } 36 | 37 | type ModuleError struct { 38 | Err string // error text 39 | } 40 | 41 | type moduleErrorNoMethods ModuleError 42 | 43 | // UnmarshalJSON accepts both {"Err":"text"} and "text", 44 | // so that the output of go mod download -json can still 45 | // be unmarshalled into a ModulePublic during -reuse processing. 46 | func (e *ModuleError) UnmarshalJSON(data []byte) error { 47 | if len(data) > 0 && data[0] == '"' { 48 | return json.Unmarshal(data, &e.Err) 49 | } 50 | return json.Unmarshal(data, (*moduleErrorNoMethods)(e)) 51 | } 52 | 53 | func (m *ModulePublic) String() string { 54 | s := m.Path 55 | versionString := func(mm *ModulePublic) string { 56 | v := mm.Version 57 | if len(mm.Retracted) == 0 { 58 | return v 59 | } 60 | return v + " (retracted)" 61 | } 62 | 63 | if m.Version != "" { 64 | s += " " + versionString(m) 65 | if m.Update != nil { 66 | s += " [" + versionString(m.Update) + "]" 67 | } 68 | } 69 | if m.Deprecated != "" { 70 | s += " (deprecated)" 71 | } 72 | if m.Replace != nil { 73 | s += " => " + m.Replace.Path 74 | if m.Replace.Version != "" { 75 | s += " " + versionString(m.Replace) 76 | if m.Replace.Update != nil { 77 | s += " [" + versionString(m.Replace.Update) + "]" 78 | } 79 | } 80 | if m.Replace.Deprecated != "" { 81 | s += " (deprecated)" 82 | } 83 | } 84 | return s 85 | } 86 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/modload/help.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package modload 6 | 7 | import "github.com/octohelm/cuemod/internal/cmd/go/internals/base" 8 | 9 | var HelpModules = &base.Command{ 10 | UsageLine: "modules", 11 | Short: "modules, module versions, and more", 12 | Long: ` 13 | Modules are how Go manages dependencies. 14 | 15 | A module is a collection of packages that are released, versioned, and 16 | distributed together. Modules may be downloaded directly from version control 17 | repositories or from module proxy servers. 18 | 19 | For a series of tutorials on modules, see 20 | https://golang.org/doc/tutorial/create-module. 21 | 22 | For a detailed reference on modules, see https://golang.org/ref/mod. 23 | 24 | By default, the go command may download modules from https://proxy.golang.org. 25 | It may authenticate modules using the checksum database at 26 | https://sum.golang.org. Both services are operated by the Go team at Google. 27 | The privacy policies for these services are available at 28 | https://proxy.golang.org/privacy and https://sum.golang.org/privacy, 29 | respectively. 30 | 31 | The go command's download behavior may be configured using GOPROXY, GOSUMDB, 32 | GOPRIVATE, and other environment variables. See 'go help environment' 33 | and https://golang.org/ref/mod#private-module-privacy for more information. 34 | `, 35 | } 36 | 37 | var HelpGoMod = &base.Command{ 38 | UsageLine: "go.mod", 39 | Short: "the go.mod file", 40 | Long: ` 41 | A module version is defined by a tree of source files, with a go.mod 42 | file in its root. When the go command is run, it looks in the current 43 | directory and then successive parent directories to find the go.mod 44 | marking the root of the main (current) module. 45 | 46 | The go.mod file format is described in detail at 47 | https://golang.org/ref/mod#go-mod-file. 48 | 49 | To create a new go.mod file, use 'go mod init'. For details see 50 | 'go help mod init' or https://golang.org/ref/mod#go-mod-init. 51 | 52 | To add missing module requirements or remove unneeded requirements, 53 | use 'go mod tidy'. For details, see 'go help mod tidy' or 54 | https://golang.org/ref/mod#go-mod-tidy. 55 | 56 | To add, upgrade, downgrade, or remove a specific module requirement, use 57 | 'go get'. For details, see 'go help module-get' or 58 | https://golang.org/ref/mod#go-get. 59 | 60 | To make other changes or to parse go.mod as JSON for use by other tools, 61 | use 'go mod edit'. See 'go help mod edit' or 62 | https://golang.org/ref/mod#go-mod-edit. 63 | `, 64 | } 65 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/modload/stat_openfile.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build (js && wasm) || plan9 6 | 7 | // On plan9, per http://9p.io/magic/man2html/2/access: “Since file permissions 8 | // are checked by the server and group information is not known to the client, 9 | // access must open the file to check permissions.” 10 | // 11 | // js,wasm is similar, in that it does not define syscall.Access. 12 | 13 | package modload 14 | 15 | import ( 16 | "io/fs" 17 | "os" 18 | ) 19 | 20 | // hasWritePerm reports whether the current user has permission to write to the 21 | // file with the given info. 22 | func hasWritePerm(path string, _ fs.FileInfo) bool { 23 | if f, err := os.OpenFile(path, os.O_WRONLY, 0); err == nil { 24 | f.Close() 25 | return true 26 | } 27 | return false 28 | } 29 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/modload/stat_unix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build unix 6 | 7 | package modload 8 | 9 | import ( 10 | "io/fs" 11 | "os" 12 | "syscall" 13 | ) 14 | 15 | // hasWritePerm reports whether the current user has permission to write to the 16 | // file with the given info. 17 | // 18 | // Although the root user on most Unix systems can write to files even without 19 | // permission, hasWritePerm reports false if no appropriate permission bit is 20 | // set even if the current user is root. 21 | func hasWritePerm(path string, fi fs.FileInfo) bool { 22 | if os.Getuid() == 0 { 23 | // The root user can access any file, but we still want to default to 24 | // read-only mode if the go.mod file is marked as globally non-writable. 25 | // (If the user really intends not to be in readonly mode, they can 26 | // pass -mod=mod explicitly.) 27 | return fi.Mode()&0222 != 0 28 | } 29 | 30 | const W_OK = 0x2 31 | return syscall.Access(path, W_OK) == nil 32 | } 33 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/modload/stat_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build windows 6 | 7 | package modload 8 | 9 | import "io/fs" 10 | 11 | // hasWritePerm reports whether the current user has permission to write to the 12 | // file with the given info. 13 | func hasWritePerm(_ string, fi fs.FileInfo) bool { 14 | // Windows has a read-only attribute independent of ACLs, so use that to 15 | // determine whether the file is intended to be overwritten. 16 | // 17 | // Per https://golang.org/pkg/os/#Chmod: 18 | // “On Windows, only the 0200 bit (owner writable) of mode is used; it 19 | // controls whether the file's read-only attribute is set or cleared.” 20 | return fi.Mode()&0200 != 0 21 | } 22 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/mvs/errors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package mvs 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | 11 | "golang.org/x/mod/module" 12 | ) 13 | 14 | // BuildListError decorates an error that occurred gathering requirements 15 | // while constructing a build list. BuildListError prints the chain 16 | // of requirements to the module where the error occurred. 17 | type BuildListError struct { 18 | Err error 19 | stack []buildListErrorElem 20 | } 21 | 22 | type buildListErrorElem struct { 23 | m module.Version 24 | 25 | // nextReason is the reason this module depends on the next module in the 26 | // stack. Typically either "requires", or "updating to". 27 | nextReason string 28 | } 29 | 30 | // NewBuildListError returns a new BuildListError wrapping an error that 31 | // occurred at a module found along the given path of requirements and/or 32 | // upgrades, which must be non-empty. 33 | // 34 | // The isVersionChange function reports whether a path step is due to an 35 | // explicit upgrade or downgrade (as opposed to an existing requirement in a 36 | // go.mod file). A nil isVersionChange function indicates that none of the path 37 | // steps are due to explicit version changes. 38 | func NewBuildListError(err error, path []module.Version, isVersionChange func(from, to module.Version) bool) *BuildListError { 39 | stack := make([]buildListErrorElem, 0, len(path)) 40 | for len(path) > 1 { 41 | reason := "requires" 42 | if isVersionChange != nil && isVersionChange(path[0], path[1]) { 43 | reason = "updating to" 44 | } 45 | stack = append(stack, buildListErrorElem{ 46 | m: path[0], 47 | nextReason: reason, 48 | }) 49 | path = path[1:] 50 | } 51 | stack = append(stack, buildListErrorElem{m: path[0]}) 52 | 53 | return &BuildListError{ 54 | Err: err, 55 | stack: stack, 56 | } 57 | } 58 | 59 | // Module returns the module where the error occurred. If the module stack 60 | // is empty, this returns a zero value. 61 | func (e *BuildListError) Module() module.Version { 62 | if len(e.stack) == 0 { 63 | return module.Version{} 64 | } 65 | return e.stack[len(e.stack)-1].m 66 | } 67 | 68 | func (e *BuildListError) Error() string { 69 | b := &strings.Builder{} 70 | stack := e.stack 71 | 72 | // Don't print modules at the beginning of the chain without a 73 | // version. These always seem to be the main module or a 74 | // synthetic module ("target@"). 75 | for len(stack) > 0 && stack[0].m.Version == "" { 76 | stack = stack[1:] 77 | } 78 | 79 | if len(stack) == 0 { 80 | b.WriteString(e.Err.Error()) 81 | } else { 82 | for _, elem := range stack[:len(stack)-1] { 83 | fmt.Fprintf(b, "%s %s\n\t", elem.m, elem.nextReason) 84 | } 85 | // Ensure that the final module path and version are included as part of the 86 | // error message. 87 | m := stack[len(stack)-1].m 88 | if mErr, ok := e.Err.(*module.ModuleError); ok { 89 | actual := module.Version{Path: mErr.Path, Version: mErr.Version} 90 | if v, ok := mErr.Err.(*module.InvalidVersionError); ok { 91 | actual.Version = v.Version 92 | } 93 | if actual == m { 94 | fmt.Fprintf(b, "%v", e.Err) 95 | } else { 96 | fmt.Fprintf(b, "%s (replaced by %s): %v", m, actual, mErr.Err) 97 | } 98 | } else { 99 | fmt.Fprintf(b, "%v", module.VersionError(m, e.Err)) 100 | } 101 | } 102 | return b.String() 103 | } 104 | 105 | func (e *BuildListError) Unwrap() error { return e.Err } 106 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/par/queue.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package par 6 | 7 | import "fmt" 8 | 9 | // Queue manages a set of work items to be executed in parallel. The number of 10 | // active work items is limited, and excess items are queued sequentially. 11 | type Queue struct { 12 | maxActive int 13 | st chan queueState 14 | } 15 | 16 | type queueState struct { 17 | active int // number of goroutines processing work; always nonzero when len(backlog) > 0 18 | backlog []func() 19 | idle chan struct{} // if non-nil, closed when active becomes 0 20 | } 21 | 22 | // NewQueue returns a Queue that executes up to maxActive items in parallel. 23 | // 24 | // maxActive must be positive. 25 | func NewQueue(maxActive int) *Queue { 26 | if maxActive < 1 { 27 | panic(fmt.Sprintf("par.NewQueue called with nonpositive limit (%d)", maxActive)) 28 | } 29 | 30 | q := &Queue{ 31 | maxActive: maxActive, 32 | st: make(chan queueState, 1), 33 | } 34 | q.st <- queueState{} 35 | return q 36 | } 37 | 38 | // Add adds f as a work item in the queue. 39 | // 40 | // Add returns immediately, but the queue will be marked as non-idle until after 41 | // f (and any subsequently-added work) has completed. 42 | func (q *Queue) Add(f func()) { 43 | st := <-q.st 44 | if st.active == q.maxActive { 45 | st.backlog = append(st.backlog, f) 46 | q.st <- st 47 | return 48 | } 49 | if st.active == 0 { 50 | // Mark q as non-idle. 51 | st.idle = nil 52 | } 53 | st.active++ 54 | q.st <- st 55 | 56 | go func() { 57 | for { 58 | f() 59 | 60 | st := <-q.st 61 | if len(st.backlog) == 0 { 62 | if st.active--; st.active == 0 && st.idle != nil { 63 | close(st.idle) 64 | } 65 | q.st <- st 66 | return 67 | } 68 | f, st.backlog = st.backlog[0], st.backlog[1:] 69 | q.st <- st 70 | } 71 | }() 72 | } 73 | 74 | // Idle returns a channel that will be closed when q has no (active or enqueued) 75 | // work outstanding. 76 | func (q *Queue) Idle() <-chan struct{} { 77 | st := <-q.st 78 | defer func() { q.st <- st }() 79 | 80 | if st.idle == nil { 81 | st.idle = make(chan struct{}) 82 | if st.active == 0 { 83 | close(st.idle) 84 | } 85 | } 86 | 87 | return st.idle 88 | } 89 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/robustio/robustio.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package robustio wraps I/O functions that are prone to failure on Windows, 6 | // transparently retrying errors up to an arbitrary timeout. 7 | // 8 | // Errors are classified heuristically and retries are bounded, so the functions 9 | // in this package do not completely eliminate spurious errors. However, they do 10 | // significantly reduce the rate of failure in practice. 11 | // 12 | // If so, the error will likely wrap one of: 13 | // The functions in this package do not completely eliminate spurious errors, 14 | // but substantially reduce their rate of occurrence in practice. 15 | package robustio 16 | 17 | // Rename is like os.Rename, but on Windows retries errors that may occur if the 18 | // file is concurrently read or overwritten. 19 | // 20 | // (See golang.org/issue/31247 and golang.org/issue/32188.) 21 | func Rename(oldpath, newpath string) error { 22 | return rename(oldpath, newpath) 23 | } 24 | 25 | // ReadFile is like os.ReadFile, but on Windows retries errors that may 26 | // occur if the file is concurrently replaced. 27 | // 28 | // (See golang.org/issue/31247 and golang.org/issue/32188.) 29 | func ReadFile(filename string) ([]byte, error) { 30 | return readFile(filename) 31 | } 32 | 33 | // RemoveAll is like os.RemoveAll, but on Windows retries errors that may occur 34 | // if an executable file in the directory has recently been executed. 35 | // 36 | // (See golang.org/issue/19491.) 37 | func RemoveAll(path string) error { 38 | return removeAll(path) 39 | } 40 | 41 | // IsEphemeralError reports whether err is one of the errors that the functions 42 | // in this package attempt to mitigate. 43 | // 44 | // Errors considered ephemeral include: 45 | // - syscall.ERROR_ACCESS_DENIED 46 | // - syscall.ERROR_FILE_NOT_FOUND 47 | // - internal/syscall/windows.ERROR_SHARING_VIOLATION 48 | // 49 | // This set may be expanded in the future; programs must not rely on the 50 | // non-ephemerality of any given error. 51 | func IsEphemeralError(err error) bool { 52 | return isEphemeralError(err) 53 | } 54 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/robustio/robustio_darwin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package robustio 6 | 7 | import ( 8 | "errors" 9 | "syscall" 10 | ) 11 | 12 | const errFileNotFound = syscall.ENOENT 13 | 14 | // isEphemeralError returns true if err may be resolved by waiting. 15 | func isEphemeralError(err error) bool { 16 | var errno syscall.Errno 17 | if errors.As(err, &errno) { 18 | return errno == errFileNotFound 19 | } 20 | return false 21 | } 22 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/robustio/robustio_flaky.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build windows || darwin 6 | 7 | package robustio 8 | 9 | import ( 10 | "errors" 11 | "math/rand" 12 | "os" 13 | "syscall" 14 | "time" 15 | ) 16 | 17 | const arbitraryTimeout = 2000 * time.Millisecond 18 | 19 | // retry retries ephemeral errors from f up to an arbitrary timeout 20 | // to work around filesystem flakiness on Windows and Darwin. 21 | func retry(f func() (err error, mayRetry bool)) error { 22 | var ( 23 | bestErr error 24 | lowestErrno syscall.Errno 25 | start time.Time 26 | nextSleep time.Duration = 1 * time.Millisecond 27 | ) 28 | for { 29 | err, mayRetry := f() 30 | if err == nil || !mayRetry { 31 | return err 32 | } 33 | 34 | var errno syscall.Errno 35 | if errors.As(err, &errno) && (lowestErrno == 0 || errno < lowestErrno) { 36 | bestErr = err 37 | lowestErrno = errno 38 | } else if bestErr == nil { 39 | bestErr = err 40 | } 41 | 42 | if start.IsZero() { 43 | start = time.Now() 44 | } else if d := time.Since(start) + nextSleep; d >= arbitraryTimeout { 45 | break 46 | } 47 | time.Sleep(nextSleep) 48 | nextSleep += time.Duration(rand.Int63n(int64(nextSleep))) 49 | } 50 | 51 | return bestErr 52 | } 53 | 54 | // rename is like os.Rename, but retries ephemeral errors. 55 | // 56 | // On Windows it wraps os.Rename, which (as of 2019-06-04) uses MoveFileEx with 57 | // MOVEFILE_REPLACE_EXISTING. 58 | // 59 | // Windows also provides a different system call, ReplaceFile, 60 | // that provides similar semantics, but perhaps preserves more metadata. (The 61 | // documentation on the differences between the two is very sparse.) 62 | // 63 | // Empirical error rates with MoveFileEx are lower under modest concurrency, so 64 | // for now we're sticking with what the os package already provides. 65 | func rename(oldpath, newpath string) (err error) { 66 | return retry(func() (err error, mayRetry bool) { 67 | err = os.Rename(oldpath, newpath) 68 | return err, isEphemeralError(err) 69 | }) 70 | } 71 | 72 | // readFile is like os.ReadFile, but retries ephemeral errors. 73 | func readFile(filename string) ([]byte, error) { 74 | var b []byte 75 | err := retry(func() (err error, mayRetry bool) { 76 | b, err = os.ReadFile(filename) 77 | 78 | // Unlike in rename, we do not retry errFileNotFound here: it can occur 79 | // as a spurious error, but the file may also genuinely not exist, so the 80 | // increase in robustness is probably not worth the extra latency. 81 | return err, isEphemeralError(err) && !errors.Is(err, errFileNotFound) 82 | }) 83 | return b, err 84 | } 85 | 86 | func removeAll(path string) error { 87 | return retry(func() (err error, mayRetry bool) { 88 | err = os.RemoveAll(path) 89 | return err, isEphemeralError(err) 90 | }) 91 | } 92 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/robustio/robustio_other.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !windows && !darwin 6 | 7 | package robustio 8 | 9 | import ( 10 | "os" 11 | ) 12 | 13 | func rename(oldpath, newpath string) error { 14 | return os.Rename(oldpath, newpath) 15 | } 16 | 17 | func readFile(filename string) ([]byte, error) { 18 | return os.ReadFile(filename) 19 | } 20 | 21 | func removeAll(path string) error { 22 | return os.RemoveAll(path) 23 | } 24 | 25 | func isEphemeralError(err error) bool { 26 | return false 27 | } 28 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/robustio/robustio_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package robustio 6 | 7 | import ( 8 | "errors" 9 | "github.com/octohelm/cuemod/internal/internals/syscall/windows" 10 | "syscall" 11 | ) 12 | 13 | const errFileNotFound = syscall.ERROR_FILE_NOT_FOUND 14 | 15 | // isEphemeralError returns true if err may be resolved by waiting. 16 | func isEphemeralError(err error) bool { 17 | var errno syscall.Errno 18 | if errors.As(err, &errno) { 19 | switch errno { 20 | case syscall.ERROR_ACCESS_DENIED, 21 | syscall.ERROR_FILE_NOT_FOUND, 22 | windows.ERROR_SHARING_VIOLATION: 23 | return true 24 | } 25 | } 26 | return false 27 | } 28 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/str/str.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package str provides string manipulation utilities. 6 | package str 7 | 8 | import ( 9 | "fmt" 10 | "strings" 11 | "unicode" 12 | "unicode/utf8" 13 | ) 14 | 15 | // StringList flattens its arguments into a single []string. 16 | // Each argument in args must have type string or []string. 17 | func StringList(args ...any) []string { 18 | var x []string 19 | for _, arg := range args { 20 | switch arg := arg.(type) { 21 | case []string: 22 | x = append(x, arg...) 23 | case string: 24 | x = append(x, arg) 25 | default: 26 | panic("stringList: invalid argument of type " + fmt.Sprintf("%T", arg)) 27 | } 28 | } 29 | return x 30 | } 31 | 32 | // ToFold returns a string with the property that 33 | // 34 | // strings.EqualFold(s, t) iff ToFold(s) == ToFold(t) 35 | // 36 | // This lets us test a large set of strings for fold-equivalent 37 | // duplicates without making a quadratic number of calls 38 | // to EqualFold. Note that strings.ToUpper and strings.ToLower 39 | // do not have the desired property in some corner cases. 40 | func ToFold(s string) string { 41 | // Fast path: all ASCII, no upper case. 42 | // Most paths look like this already. 43 | for i := 0; i < len(s); i++ { 44 | c := s[i] 45 | if c >= utf8.RuneSelf || 'A' <= c && c <= 'Z' { 46 | goto Slow 47 | } 48 | } 49 | return s 50 | 51 | Slow: 52 | var b strings.Builder 53 | for _, r := range s { 54 | // SimpleFold(x) cycles to the next equivalent rune > x 55 | // or wraps around to smaller values. Iterate until it wraps, 56 | // and we've found the minimum value. 57 | for { 58 | r0 := r 59 | r = unicode.SimpleFold(r0) 60 | if r <= r0 { 61 | break 62 | } 63 | } 64 | // Exception to allow fast path above: A-Z => a-z 65 | if 'A' <= r && r <= 'Z' { 66 | r += 'a' - 'A' 67 | } 68 | b.WriteRune(r) 69 | } 70 | return b.String() 71 | } 72 | 73 | // FoldDup reports a pair of strings from the list that are 74 | // equal according to strings.EqualFold. 75 | // It returns "", "" if there are no such strings. 76 | func FoldDup(list []string) (string, string) { 77 | clash := map[string]string{} 78 | for _, s := range list { 79 | fold := ToFold(s) 80 | if t := clash[fold]; t != "" { 81 | if s > t { 82 | s, t = t, s 83 | } 84 | return s, t 85 | } 86 | clash[fold] = s 87 | } 88 | return "", "" 89 | } 90 | 91 | // Contains reports whether x contains s. 92 | func Contains(x []string, s string) bool { 93 | for _, t := range x { 94 | if t == s { 95 | return true 96 | } 97 | } 98 | return false 99 | } 100 | 101 | // Uniq removes consecutive duplicate strings from ss. 102 | func Uniq(ss *[]string) { 103 | if len(*ss) <= 1 { 104 | return 105 | } 106 | uniq := (*ss)[:1] 107 | for _, s := range *ss { 108 | if s != uniq[len(uniq)-1] { 109 | uniq = append(uniq, s) 110 | } 111 | } 112 | *ss = uniq 113 | } 114 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/vcs/discovery.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package vcs 6 | 7 | import ( 8 | "encoding/xml" 9 | "fmt" 10 | "io" 11 | "strings" 12 | ) 13 | 14 | // charsetReader returns a reader that converts from the given charset to UTF-8. 15 | // Currently it only supports UTF-8 and ASCII. Otherwise, it returns a meaningful 16 | // error which is printed by go get, so the user can find why the package 17 | // wasn't downloaded if the encoding is not supported. Note that, in 18 | // order to reduce potential errors, ASCII is treated as UTF-8 (i.e. characters 19 | // greater than 0x7f are not rejected). 20 | func charsetReader(charset string, input io.Reader) (io.Reader, error) { 21 | switch strings.ToLower(charset) { 22 | case "utf-8", "ascii": 23 | return input, nil 24 | default: 25 | return nil, fmt.Errorf("can't decode XML document using charset %q", charset) 26 | } 27 | } 28 | 29 | // parseMetaGoImports returns meta imports from the HTML in r. 30 | // Parsing ends at the end of the section or the beginning of the . 31 | func parseMetaGoImports(r io.Reader, mod ModuleMode) ([]metaImport, error) { 32 | d := xml.NewDecoder(r) 33 | d.CharsetReader = charsetReader 34 | d.Strict = false 35 | var imports []metaImport 36 | for { 37 | t, err := d.RawToken() 38 | if err != nil { 39 | if err != io.EOF && len(imports) == 0 { 40 | return nil, err 41 | } 42 | break 43 | } 44 | if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") { 45 | break 46 | } 47 | if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") { 48 | break 49 | } 50 | e, ok := t.(xml.StartElement) 51 | if !ok || !strings.EqualFold(e.Name.Local, "meta") { 52 | continue 53 | } 54 | if attrValue(e.Attr, "name") != "go-import" { 55 | continue 56 | } 57 | if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 { 58 | imports = append(imports, metaImport{ 59 | Prefix: f[0], 60 | VCS: f[1], 61 | RepoRoot: f[2], 62 | }) 63 | } 64 | } 65 | 66 | // Extract mod entries if we are paying attention to them. 67 | var list []metaImport 68 | var have map[string]bool 69 | if mod == PreferMod { 70 | have = make(map[string]bool) 71 | for _, m := range imports { 72 | if m.VCS == "mod" { 73 | have[m.Prefix] = true 74 | list = append(list, m) 75 | } 76 | } 77 | } 78 | 79 | // Append non-mod entries, ignoring those superseded by a mod entry. 80 | for _, m := range imports { 81 | if m.VCS != "mod" && !have[m.Prefix] { 82 | list = append(list, m) 83 | } 84 | } 85 | return list, nil 86 | } 87 | 88 | // attrValue returns the attribute value for the case-insensitive key 89 | // `name', or the empty string if nothing is found. 90 | func attrValue(attrs []xml.Attr, name string) string { 91 | for _, a := range attrs { 92 | if strings.EqualFold(a.Name.Local, name) { 93 | return a.Value 94 | } 95 | } 96 | return "" 97 | } 98 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/web/bootstrap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build cmd_go_bootstrap 6 | 7 | // This code is compiled only into the bootstrap 'go' binary. 8 | // These stubs avoid importing packages with large dependency 9 | // trees that potentially require C linking, 10 | // like the use of "net/http" in vcs.go. 11 | 12 | package web 13 | 14 | import ( 15 | "errors" 16 | urlpkg "net/url" 17 | ) 18 | 19 | func get(security SecurityMode, url *urlpkg.URL) (*Response, error) { 20 | return nil, errors.New("no http in bootstrap go command") 21 | } 22 | 23 | func openBrowser(url string) bool { return false } 24 | 25 | func isLocalHost(u *urlpkg.URL) bool { return false } 26 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/web/url.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package web 6 | 7 | import ( 8 | "errors" 9 | "net/url" 10 | "path/filepath" 11 | "strings" 12 | ) 13 | 14 | // TODO(golang.org/issue/32456): If accepted, move these functions into the 15 | // net/url package. 16 | 17 | var errNotAbsolute = errors.New("path is not absolute") 18 | 19 | func urlToFilePath(u *url.URL) (string, error) { 20 | if u.Scheme != "file" { 21 | return "", errors.New("non-file URL") 22 | } 23 | 24 | checkAbs := func(path string) (string, error) { 25 | if !filepath.IsAbs(path) { 26 | return "", errNotAbsolute 27 | } 28 | return path, nil 29 | } 30 | 31 | if u.Path == "" { 32 | if u.Host != "" || u.Opaque == "" { 33 | return "", errors.New("file URL missing path") 34 | } 35 | return checkAbs(filepath.FromSlash(u.Opaque)) 36 | } 37 | 38 | path, err := convertFileURLPath(u.Host, u.Path) 39 | if err != nil { 40 | return path, err 41 | } 42 | return checkAbs(path) 43 | } 44 | 45 | func urlFromFilePath(path string) (*url.URL, error) { 46 | if !filepath.IsAbs(path) { 47 | return nil, errNotAbsolute 48 | } 49 | 50 | // If path has a Windows volume name, convert the volume to a host and prefix 51 | // per https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/. 52 | if vol := filepath.VolumeName(path); vol != "" { 53 | if strings.HasPrefix(vol, `\\`) { 54 | path = filepath.ToSlash(path[2:]) 55 | i := strings.IndexByte(path, '/') 56 | 57 | if i < 0 { 58 | // A degenerate case. 59 | // \\host.example.com (without a share name) 60 | // becomes 61 | // file://host.example.com/ 62 | return &url.URL{ 63 | Scheme: "file", 64 | Host: path, 65 | Path: "/", 66 | }, nil 67 | } 68 | 69 | // \\host.example.com\Share\path\to\file 70 | // becomes 71 | // file://host.example.com/Share/path/to/file 72 | return &url.URL{ 73 | Scheme: "file", 74 | Host: path[:i], 75 | Path: filepath.ToSlash(path[i:]), 76 | }, nil 77 | } 78 | 79 | // C:\path\to\file 80 | // becomes 81 | // file:///C:/path/to/file 82 | return &url.URL{ 83 | Scheme: "file", 84 | Path: "/" + filepath.ToSlash(path), 85 | }, nil 86 | } 87 | 88 | // /path/to/file 89 | // becomes 90 | // file:///path/to/file 91 | return &url.URL{ 92 | Scheme: "file", 93 | Path: filepath.ToSlash(path), 94 | }, nil 95 | } 96 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/web/url_other.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !windows 6 | 7 | package web 8 | 9 | import ( 10 | "errors" 11 | "path/filepath" 12 | ) 13 | 14 | func convertFileURLPath(host, path string) (string, error) { 15 | switch host { 16 | case "", "localhost": 17 | default: 18 | return "", errors.New("file URL specifies non-local host") 19 | } 20 | return filepath.FromSlash(path), nil 21 | } 22 | -------------------------------------------------------------------------------- /internal/cmd/go/internals/web/url_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package web 6 | 7 | import ( 8 | "errors" 9 | "path/filepath" 10 | "strings" 11 | ) 12 | 13 | func convertFileURLPath(host, path string) (string, error) { 14 | if len(path) == 0 || path[0] != '/' { 15 | return "", errNotAbsolute 16 | } 17 | 18 | path = filepath.FromSlash(path) 19 | 20 | // We interpret Windows file URLs per the description in 21 | // https://blogs.msdn.microsoft.com/ie/2006/12/06/file-uris-in-windows/. 22 | 23 | // The host part of a file URL (if any) is the UNC volume name, 24 | // but RFC 8089 reserves the authority "localhost" for the local machine. 25 | if host != "" && host != "localhost" { 26 | // A common "legacy" format omits the leading slash before a drive letter, 27 | // encoding the drive letter as the host instead of part of the path. 28 | // (See https://blogs.msdn.microsoft.com/freeassociations/2005/05/19/the-bizarre-and-unhappy-story-of-file-urls/.) 29 | // We do not support that format, but we should at least emit a more 30 | // helpful error message for it. 31 | if filepath.VolumeName(host) != "" { 32 | return "", errors.New("file URL encodes volume in host field: too few slashes?") 33 | } 34 | return `\\` + host + path, nil 35 | } 36 | 37 | // If host is empty, path must contain an initial slash followed by a 38 | // drive letter and path. Remove the slash and verify that the path is valid. 39 | if vol := filepath.VolumeName(path[1:]); vol == "" || strings.HasPrefix(vol, `\\`) { 40 | return "", errors.New("file URL missing drive letter") 41 | } 42 | return path[1:], nil 43 | } 44 | -------------------------------------------------------------------------------- /internal/cmd/internals/browser/browser.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package browser provides utilities for interacting with users' browsers. 6 | package browser 7 | 8 | import ( 9 | "os" 10 | "os/exec" 11 | "runtime" 12 | "time" 13 | ) 14 | 15 | // Commands returns a list of possible commands to use to open a url. 16 | func Commands() [][]string { 17 | var cmds [][]string 18 | if exe := os.Getenv("BROWSER"); exe != "" { 19 | cmds = append(cmds, []string{exe}) 20 | } 21 | switch runtime.GOOS { 22 | case "darwin": 23 | cmds = append(cmds, []string{"/usr/bin/open"}) 24 | case "windows": 25 | cmds = append(cmds, []string{"cmd", "/c", "start"}) 26 | default: 27 | if os.Getenv("DISPLAY") != "" { 28 | // xdg-open is only for use in a desktop environment. 29 | cmds = append(cmds, []string{"xdg-open"}) 30 | } 31 | } 32 | cmds = append(cmds, 33 | []string{"chrome"}, 34 | []string{"google-chrome"}, 35 | []string{"chromium"}, 36 | []string{"firefox"}, 37 | ) 38 | return cmds 39 | } 40 | 41 | // Open tries to open url in a browser and reports whether it succeeded. 42 | func Open(url string) bool { 43 | for _, args := range Commands() { 44 | cmd := exec.Command(args[0], append(args[1:], url)...) 45 | if cmd.Start() == nil && appearsSuccessful(cmd, 3*time.Second) { 46 | return true 47 | } 48 | } 49 | return false 50 | } 51 | 52 | // appearsSuccessful reports whether the command appears to have run successfully. 53 | // If the command runs longer than the timeout, it's deemed successful. 54 | // If the command runs within the timeout, it's deemed successful if it exited cleanly. 55 | func appearsSuccessful(cmd *exec.Cmd, timeout time.Duration) bool { 56 | errc := make(chan error, 1) 57 | go func() { 58 | errc <- cmd.Wait() 59 | }() 60 | 61 | select { 62 | case <-time.After(timeout): 63 | return true 64 | case err := <-errc: 65 | return err == nil 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /internal/cmd/internals/quoted/quoted.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package quoted provides string manipulation utilities. 6 | package quoted 7 | 8 | import ( 9 | "flag" 10 | "fmt" 11 | "strings" 12 | "unicode" 13 | ) 14 | 15 | func isSpaceByte(c byte) bool { 16 | return c == ' ' || c == '\t' || c == '\n' || c == '\r' 17 | } 18 | 19 | // Split splits s into a list of fields, 20 | // allowing single or double quotes around elements. 21 | // There is no unescaping or other processing within 22 | // quoted fields. 23 | // 24 | // Keep in sync with cmd/dist/quoted.go 25 | func Split(s string) ([]string, error) { 26 | // Split fields allowing '' or "" around elements. 27 | // Quotes further inside the string do not count. 28 | var f []string 29 | for len(s) > 0 { 30 | for len(s) > 0 && isSpaceByte(s[0]) { 31 | s = s[1:] 32 | } 33 | if len(s) == 0 { 34 | break 35 | } 36 | // Accepted quoted string. No unescaping inside. 37 | if s[0] == '"' || s[0] == '\'' { 38 | quote := s[0] 39 | s = s[1:] 40 | i := 0 41 | for i < len(s) && s[i] != quote { 42 | i++ 43 | } 44 | if i >= len(s) { 45 | return nil, fmt.Errorf("unterminated %c string", quote) 46 | } 47 | f = append(f, s[:i]) 48 | s = s[i+1:] 49 | continue 50 | } 51 | i := 0 52 | for i < len(s) && !isSpaceByte(s[i]) { 53 | i++ 54 | } 55 | f = append(f, s[:i]) 56 | s = s[i:] 57 | } 58 | return f, nil 59 | } 60 | 61 | // Join joins a list of arguments into a string that can be parsed 62 | // with Split. Arguments are quoted only if necessary; arguments 63 | // without spaces or quotes are kept as-is. No argument may contain both 64 | // single and double quotes. 65 | func Join(args []string) (string, error) { 66 | var buf []byte 67 | for i, arg := range args { 68 | if i > 0 { 69 | buf = append(buf, ' ') 70 | } 71 | var sawSpace, sawSingleQuote, sawDoubleQuote bool 72 | for _, c := range arg { 73 | switch { 74 | case c > unicode.MaxASCII: 75 | continue 76 | case isSpaceByte(byte(c)): 77 | sawSpace = true 78 | case c == '\'': 79 | sawSingleQuote = true 80 | case c == '"': 81 | sawDoubleQuote = true 82 | } 83 | } 84 | switch { 85 | case !sawSpace && !sawSingleQuote && !sawDoubleQuote: 86 | buf = append(buf, arg...) 87 | 88 | case !sawSingleQuote: 89 | buf = append(buf, '\'') 90 | buf = append(buf, arg...) 91 | buf = append(buf, '\'') 92 | 93 | case !sawDoubleQuote: 94 | buf = append(buf, '"') 95 | buf = append(buf, arg...) 96 | buf = append(buf, '"') 97 | 98 | default: 99 | return "", fmt.Errorf("argument %q contains both single and double quotes and cannot be quoted", arg) 100 | } 101 | } 102 | return string(buf), nil 103 | } 104 | 105 | // A Flag parses a list of string arguments encoded with Join. 106 | // It is useful for flags like cmd/link's -extldflags. 107 | type Flag []string 108 | 109 | var _ flag.Value = (*Flag)(nil) 110 | 111 | func (f *Flag) Set(v string) error { 112 | fs, err := Split(v) 113 | if err != nil { 114 | return err 115 | } 116 | *f = fs[:len(fs):len(fs)] 117 | return nil 118 | } 119 | 120 | func (f *Flag) String() string { 121 | if f == nil { 122 | return "" 123 | } 124 | s, err := Join(*f) 125 | if err != nil { 126 | return strings.Join(*f, " ") 127 | } 128 | return s 129 | } 130 | -------------------------------------------------------------------------------- /internal/internals/buildcfg/zbootstrap.go: -------------------------------------------------------------------------------- 1 | // Code generated by go tool dist; DO NOT EDIT. 2 | 3 | package buildcfg 4 | 5 | import "runtime" 6 | 7 | const defaultGO386 = `sse2` 8 | const defaultGOAMD64 = `v1` 9 | const defaultGOARM = `7` 10 | const defaultGOMIPS = `hardfloat` 11 | const defaultGOMIPS64 = `hardfloat` 12 | const defaultGOPPC64 = `power8` 13 | const defaultGOEXPERIMENT = `` 14 | const defaultGO_EXTLINK_ENABLED = `` 15 | const defaultGO_LDSO = `` 16 | const version = `go1.22.0` 17 | const defaultGOOS = runtime.GOOS 18 | const defaultGOARCH = runtime.GOARCH 19 | -------------------------------------------------------------------------------- /internal/internals/cfg/cfg.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package cfg holds configuration shared by the Go command and internal/testenv. 6 | // Definitions that don't need to be exposed outside of cmd/go should be in 7 | // cmd/go/internal/cfg instead of this package. 8 | package cfg 9 | 10 | // KnownEnv is a list of environment variables that affect the operation 11 | // of the Go command. 12 | const KnownEnv = ` 13 | AR 14 | CC 15 | CGO_CFLAGS 16 | CGO_CFLAGS_ALLOW 17 | CGO_CFLAGS_DISALLOW 18 | CGO_CPPFLAGS 19 | CGO_CPPFLAGS_ALLOW 20 | CGO_CPPFLAGS_DISALLOW 21 | CGO_CXXFLAGS 22 | CGO_CXXFLAGS_ALLOW 23 | CGO_CXXFLAGS_DISALLOW 24 | CGO_ENABLED 25 | CGO_FFLAGS 26 | CGO_FFLAGS_ALLOW 27 | CGO_FFLAGS_DISALLOW 28 | CGO_LDFLAGS 29 | CGO_LDFLAGS_ALLOW 30 | CGO_LDFLAGS_DISALLOW 31 | CXX 32 | FC 33 | GCCGO 34 | GO111MODULE 35 | GO386 36 | GOAMD64 37 | GOARCH 38 | GOARM 39 | GOBIN 40 | GOCACHE 41 | GOCACHEPROG 42 | GOENV 43 | GOEXE 44 | GOEXPERIMENT 45 | GOFLAGS 46 | GOGCCFLAGS 47 | GOHOSTARCH 48 | GOHOSTOS 49 | GOINSECURE 50 | GOMIPS 51 | GOMIPS64 52 | GOMODCACHE 53 | GONOPROXY 54 | GONOSUMDB 55 | GOOS 56 | GOPATH 57 | GOPPC64 58 | GOPRIVATE 59 | GOPROXY 60 | GOROOT 61 | GOSUMDB 62 | GOTMPDIR 63 | GOTOOLCHAIN 64 | GOTOOLDIR 65 | GOVCS 66 | GOWASM 67 | GOWORK 68 | GO_EXTLINK_ENABLED 69 | PKG_CONFIG 70 | ` 71 | -------------------------------------------------------------------------------- /internal/internals/godebugs/table.go: -------------------------------------------------------------------------------- 1 | // Copyright 2023 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package godebugs provides a table of known GODEBUG settings, 6 | // for use by a variety of other packages, including internal/godebug, 7 | // runtime, runtime/metrics, and cmd/go/internal/load. 8 | package godebugs 9 | 10 | // An Info describes a single known GODEBUG setting. 11 | type Info struct { 12 | Name string // name of the setting ("panicnil") 13 | Package string // package that uses the setting ("runtime") 14 | Changed int // minor version when default changed, if any; 21 means Go 1.21 15 | Old string // value that restores behavior prior to Changed 16 | Opaque bool // setting does not export information to runtime/metrics using [internal/godebug.Setting.IncNonDefault] 17 | } 18 | 19 | // All is the table of known settings, sorted by Name. 20 | // 21 | // Note: After adding entries to this table, run 'go generate runtime/metrics' 22 | // to update the runtime/metrics doc comment. 23 | // (Otherwise the runtime/metrics test will fail.) 24 | // 25 | // Note: After adding entries to this table, update the list in doc/godebug.md as well. 26 | // (Otherwise the test in this package will fail.) 27 | var All = []Info{ 28 | {Name: "execerrdot", Package: "os/exec"}, 29 | {Name: "gocachehash", Package: "cmd/go"}, 30 | {Name: "gocachetest", Package: "cmd/go"}, 31 | {Name: "gocacheverify", Package: "cmd/go"}, 32 | {Name: "gotypesalias", Package: "go/types"}, 33 | {Name: "http2client", Package: "net/http"}, 34 | {Name: "http2debug", Package: "net/http", Opaque: true}, 35 | {Name: "http2server", Package: "net/http"}, 36 | {Name: "httplaxcontentlength", Package: "net/http", Changed: 22, Old: "1"}, 37 | {Name: "httpmuxgo121", Package: "net/http", Changed: 22, Old: "1"}, 38 | {Name: "installgoroot", Package: "go/build"}, 39 | {Name: "jstmpllitinterp", Package: "html/template"}, 40 | //{Name: "multipartfiles", Package: "mime/multipart"}, 41 | {Name: "multipartmaxheaders", Package: "mime/multipart"}, 42 | {Name: "multipartmaxparts", Package: "mime/multipart"}, 43 | {Name: "multipathtcp", Package: "net"}, 44 | {Name: "netdns", Package: "net", Opaque: true}, 45 | {Name: "panicnil", Package: "runtime", Changed: 21, Old: "1"}, 46 | {Name: "randautoseed", Package: "math/rand"}, 47 | {Name: "tarinsecurepath", Package: "archive/tar"}, 48 | {Name: "tls10server", Package: "crypto/tls", Changed: 22, Old: "1"}, 49 | {Name: "tlsmaxrsasize", Package: "crypto/tls"}, 50 | {Name: "tlsrsakex", Package: "crypto/tls", Changed: 22, Old: "1"}, 51 | {Name: "tlsunsafeekm", Package: "crypto/tls", Changed: 22, Old: "1"}, 52 | {Name: "x509sha1", Package: "crypto/x509"}, 53 | {Name: "x509usefallbackroots", Package: "crypto/x509"}, 54 | {Name: "x509usepolicies", Package: "crypto/x509"}, 55 | {Name: "zipinsecurepath", Package: "archive/zip"}, 56 | } 57 | 58 | // Lookup returns the Info with the given name. 59 | func Lookup(name string) *Info { 60 | // binary search, avoiding import of sort. 61 | lo := 0 62 | hi := len(All) 63 | for lo < hi { 64 | m := int(uint(lo+hi) >> 1) 65 | mid := All[m].Name 66 | if name == mid { 67 | return &All[m] 68 | } 69 | if name < mid { 70 | hi = m 71 | } else { 72 | lo = m + 1 73 | } 74 | } 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_allocheaders_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.allocheaders 4 | 5 | package goexperiment 6 | 7 | const AllocHeaders = false 8 | const AllocHeadersInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_allocheaders_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.allocheaders 4 | 5 | package goexperiment 6 | 7 | const AllocHeaders = true 8 | const AllocHeadersInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_arenas_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.arenas 4 | 5 | package goexperiment 6 | 7 | const Arenas = false 8 | const ArenasInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_arenas_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.arenas 4 | 5 | package goexperiment 6 | 7 | const Arenas = true 8 | const ArenasInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_boringcrypto_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.boringcrypto 4 | 5 | package goexperiment 6 | 7 | const BoringCrypto = false 8 | const BoringCryptoInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_boringcrypto_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.boringcrypto 4 | 5 | package goexperiment 6 | 7 | const BoringCrypto = true 8 | const BoringCryptoInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_cacheprog_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.cacheprog 4 | 5 | package goexperiment 6 | 7 | const CacheProg = false 8 | const CacheProgInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_cacheprog_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.cacheprog 4 | 5 | package goexperiment 6 | 7 | const CacheProg = true 8 | const CacheProgInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_cgocheck2_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.cgocheck2 4 | 5 | package goexperiment 6 | 7 | const CgoCheck2 = false 8 | const CgoCheck2Int = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_cgocheck2_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.cgocheck2 4 | 5 | package goexperiment 6 | 7 | const CgoCheck2 = true 8 | const CgoCheck2Int = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_coverageredesign_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.coverageredesign 4 | 5 | package goexperiment 6 | 7 | const CoverageRedesign = false 8 | const CoverageRedesignInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_coverageredesign_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.coverageredesign 4 | 5 | package goexperiment 6 | 7 | const CoverageRedesign = true 8 | const CoverageRedesignInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_exectracer2_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.exectracer2 4 | // +build !goexperiment.exectracer2 5 | 6 | package goexperiment 7 | 8 | const ExecTracer2 = false 9 | const ExecTracer2Int = 0 10 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_exectracer2_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.exectracer2 4 | // +build goexperiment.exectracer2 5 | 6 | package goexperiment 7 | 8 | const ExecTracer2 = true 9 | const ExecTracer2Int = 1 10 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_fieldtrack_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.fieldtrack 4 | 5 | package goexperiment 6 | 7 | const FieldTrack = false 8 | const FieldTrackInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_fieldtrack_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.fieldtrack 4 | 5 | package goexperiment 6 | 7 | const FieldTrack = true 8 | const FieldTrackInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_heapminimum512kib_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.heapminimum512kib 4 | 5 | package goexperiment 6 | 7 | const HeapMinimum512KiB = false 8 | const HeapMinimum512KiBInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_heapminimum512kib_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.heapminimum512kib 4 | 5 | package goexperiment 6 | 7 | const HeapMinimum512KiB = true 8 | const HeapMinimum512KiBInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_loopvar_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.loopvar 4 | 5 | package goexperiment 6 | 7 | const LoopVar = false 8 | const LoopVarInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_loopvar_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.loopvar 4 | 5 | package goexperiment 6 | 7 | const LoopVar = true 8 | const LoopVarInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_newinliner_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.newinliner 4 | 5 | package goexperiment 6 | 7 | const NewInliner = false 8 | const NewInlinerInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_newinliner_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.newinliner 4 | 5 | package goexperiment 6 | 7 | const NewInliner = true 8 | const NewInlinerInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_pagetrace_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.pagetrace 4 | 5 | package goexperiment 6 | 7 | const PageTrace = false 8 | const PageTraceInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_pagetrace_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.pagetrace 4 | 5 | package goexperiment 6 | 7 | const PageTrace = true 8 | const PageTraceInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_preemptibleloops_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.preemptibleloops 4 | 5 | package goexperiment 6 | 7 | const PreemptibleLoops = false 8 | const PreemptibleLoopsInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_preemptibleloops_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.preemptibleloops 4 | 5 | package goexperiment 6 | 7 | const PreemptibleLoops = true 8 | const PreemptibleLoopsInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_rangefunc_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.rangefunc 4 | 5 | package goexperiment 6 | 7 | const RangeFunc = false 8 | const RangeFuncInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_rangefunc_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.rangefunc 4 | 5 | package goexperiment 6 | 7 | const RangeFunc = true 8 | const RangeFuncInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_regabiargs_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.regabiargs 4 | 5 | package goexperiment 6 | 7 | const RegabiArgs = false 8 | const RegabiArgsInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_regabiargs_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.regabiargs 4 | 5 | package goexperiment 6 | 7 | const RegabiArgs = true 8 | const RegabiArgsInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_regabiwrappers_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.regabiwrappers 4 | 5 | package goexperiment 6 | 7 | const RegabiWrappers = false 8 | const RegabiWrappersInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_regabiwrappers_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.regabiwrappers 4 | 5 | package goexperiment 6 | 7 | const RegabiWrappers = true 8 | const RegabiWrappersInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_staticlockranking_off.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build !goexperiment.staticlockranking 4 | 5 | package goexperiment 6 | 7 | const StaticLockRanking = false 8 | const StaticLockRankingInt = 0 9 | -------------------------------------------------------------------------------- /internal/internals/goexperiment/exp_staticlockranking_on.go: -------------------------------------------------------------------------------- 1 | // Code generated by mkconsts.go. DO NOT EDIT. 2 | 3 | //go:build goexperiment.staticlockranking 4 | 5 | package goexperiment 6 | 7 | const StaticLockRanking = true 8 | const StaticLockRankingInt = 1 9 | -------------------------------------------------------------------------------- /internal/internals/goroot/gccgo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build gccgo 6 | 7 | package goroot 8 | 9 | import ( 10 | "os" 11 | "path/filepath" 12 | ) 13 | 14 | // IsStandardPackage reports whether path is a standard package, 15 | // given goroot and compiler. 16 | func IsStandardPackage(goroot, compiler, path string) bool { 17 | switch compiler { 18 | case "gc": 19 | dir := filepath.Join(goroot, "src", path) 20 | _, err := os.Stat(dir) 21 | return err == nil 22 | case "gccgo": 23 | return stdpkg[path] 24 | default: 25 | panic("unknown compiler " + compiler) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /internal/internals/goversion/goversion.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package goversion 6 | 7 | // Version is the Go 1.x version which is currently 8 | // in development and will eventually get released. 9 | // 10 | // It should be updated at the start of each development cycle to be 11 | // the version of the next Go 1.x release. See golang.org/issue/40705. 12 | const Version = 22 13 | -------------------------------------------------------------------------------- /internal/internals/lazyregexp/lazyre.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package lazyregexp is a thin wrapper over regexp, allowing the use of global 6 | // regexp variables without forcing them to be compiled at init. 7 | package lazyregexp 8 | 9 | import ( 10 | "os" 11 | "regexp" 12 | "strings" 13 | "sync" 14 | ) 15 | 16 | // Regexp is a wrapper around regexp.Regexp, where the underlying regexp will be 17 | // compiled the first time it is needed. 18 | type Regexp struct { 19 | str string 20 | once sync.Once 21 | rx *regexp.Regexp 22 | } 23 | 24 | func (r *Regexp) re() *regexp.Regexp { 25 | r.once.Do(r.build) 26 | return r.rx 27 | } 28 | 29 | func (r *Regexp) build() { 30 | r.rx = regexp.MustCompile(r.str) 31 | r.str = "" 32 | } 33 | 34 | func (r *Regexp) FindSubmatch(s []byte) [][]byte { 35 | return r.re().FindSubmatch(s) 36 | } 37 | 38 | func (r *Regexp) FindStringSubmatch(s string) []string { 39 | return r.re().FindStringSubmatch(s) 40 | } 41 | 42 | func (r *Regexp) FindStringSubmatchIndex(s string) []int { 43 | return r.re().FindStringSubmatchIndex(s) 44 | } 45 | 46 | func (r *Regexp) ReplaceAllString(src, repl string) string { 47 | return r.re().ReplaceAllString(src, repl) 48 | } 49 | 50 | func (r *Regexp) FindString(s string) string { 51 | return r.re().FindString(s) 52 | } 53 | 54 | func (r *Regexp) FindAllString(s string, n int) []string { 55 | return r.re().FindAllString(s, n) 56 | } 57 | 58 | func (r *Regexp) MatchString(s string) bool { 59 | return r.re().MatchString(s) 60 | } 61 | 62 | func (r *Regexp) SubexpNames() []string { 63 | return r.re().SubexpNames() 64 | } 65 | 66 | var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test") 67 | 68 | // New creates a new lazy regexp, delaying the compiling work until it is first 69 | // needed. If the code is being run as part of tests, the regexp compiling will 70 | // happen immediately. 71 | func New(str string) *Regexp { 72 | lr := &Regexp{str: str} 73 | if inTest { 74 | // In tests, always compile the regexps early. 75 | lr.re() 76 | } 77 | return lr 78 | } 79 | -------------------------------------------------------------------------------- /internal/internals/singleflight/singleflight.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package singleflight provides a duplicate function call suppression 6 | // mechanism. 7 | package singleflight 8 | 9 | import "sync" 10 | 11 | // call is an in-flight or completed singleflight.Do call 12 | type call struct { 13 | wg sync.WaitGroup 14 | 15 | // These fields are written once before the WaitGroup is done 16 | // and are only read after the WaitGroup is done. 17 | val any 18 | err error 19 | 20 | // These fields are read and written with the singleflight 21 | // mutex held before the WaitGroup is done, and are read but 22 | // not written after the WaitGroup is done. 23 | dups int 24 | chans []chan<- Result 25 | } 26 | 27 | // Group represents a class of work and forms a namespace in 28 | // which units of work can be executed with duplicate suppression. 29 | type Group struct { 30 | mu sync.Mutex // protects m 31 | m map[string]*call // lazily initialized 32 | } 33 | 34 | // Result holds the results of Do, so they can be passed 35 | // on a channel. 36 | type Result struct { 37 | Val any 38 | Err error 39 | Shared bool 40 | } 41 | 42 | // Do executes and returns the results of the given function, making 43 | // sure that only one execution is in-flight for a given key at a 44 | // time. If a duplicate comes in, the duplicate caller waits for the 45 | // original to complete and receives the same results. 46 | // The return value shared indicates whether v was given to multiple callers. 47 | func (g *Group) Do(key string, fn func() (any, error)) (v any, err error, shared bool) { 48 | g.mu.Lock() 49 | if g.m == nil { 50 | g.m = make(map[string]*call) 51 | } 52 | if c, ok := g.m[key]; ok { 53 | c.dups++ 54 | g.mu.Unlock() 55 | c.wg.Wait() 56 | return c.val, c.err, true 57 | } 58 | c := new(call) 59 | c.wg.Add(1) 60 | g.m[key] = c 61 | g.mu.Unlock() 62 | 63 | g.doCall(c, key, fn) 64 | return c.val, c.err, c.dups > 0 65 | } 66 | 67 | // DoChan is like Do but returns a channel that will receive the 68 | // results when they are ready. 69 | func (g *Group) DoChan(key string, fn func() (any, error)) <-chan Result { 70 | ch := make(chan Result, 1) 71 | g.mu.Lock() 72 | if g.m == nil { 73 | g.m = make(map[string]*call) 74 | } 75 | if c, ok := g.m[key]; ok { 76 | c.dups++ 77 | c.chans = append(c.chans, ch) 78 | g.mu.Unlock() 79 | return ch 80 | } 81 | c := &call{chans: []chan<- Result{ch}} 82 | c.wg.Add(1) 83 | g.m[key] = c 84 | g.mu.Unlock() 85 | 86 | go g.doCall(c, key, fn) 87 | 88 | return ch 89 | } 90 | 91 | // doCall handles the single call for a key. 92 | func (g *Group) doCall(c *call, key string, fn func() (any, error)) { 93 | c.val, c.err = fn() 94 | 95 | g.mu.Lock() 96 | c.wg.Done() 97 | if g.m[key] == c { 98 | delete(g.m, key) 99 | } 100 | for _, ch := range c.chans { 101 | ch <- Result{c.val, c.err, c.dups > 0} 102 | } 103 | g.mu.Unlock() 104 | } 105 | 106 | // ForgetUnshared tells the singleflight to forget about a key if it is not 107 | // shared with any other goroutines. Future calls to Do for a forgotten key 108 | // will call the function rather than waiting for an earlier call to complete. 109 | // Returns whether the key was forgotten or unknown--that is, whether no 110 | // other goroutines are waiting for the result. 111 | func (g *Group) ForgetUnshared(key string) bool { 112 | g.mu.Lock() 113 | defer g.mu.Unlock() 114 | c, ok := g.m[key] 115 | if !ok { 116 | return true 117 | } 118 | if c.dups == 0 { 119 | delete(g.m, key) 120 | return true 121 | } 122 | return false 123 | } 124 | -------------------------------------------------------------------------------- /internal/internals/syscall/windows/memory_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package windows 6 | 7 | type MemoryBasicInformation struct { 8 | // A pointer to the base address of the region of pages. 9 | BaseAddress uintptr 10 | // A pointer to the base address of a range of pages allocated by the VirtualAlloc function. 11 | // The page pointed to by the BaseAddress member is contained within this allocation range. 12 | AllocationBase uintptr 13 | // The memory protection option when the region was initially allocated 14 | AllocationProtect uint32 15 | PartitionId uint16 16 | // The size of the region beginning at the base address in which all pages have identical attributes, in bytes. 17 | RegionSize uintptr 18 | // The state of the pages in the region. 19 | State uint32 20 | // The access protection of the pages in the region. 21 | Protect uint32 22 | // The type of pages in the region. 23 | Type uint32 24 | } 25 | -------------------------------------------------------------------------------- /internal/internals/syscall/windows/mksyscall.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build generate 6 | 7 | package windows 8 | 9 | //go:generate go run ../../../syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go security_windows.go psapi_windows.go symlink_windows.go 10 | -------------------------------------------------------------------------------- /internal/internals/syscall/windows/net_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package windows 6 | 7 | import ( 8 | "sync" 9 | "syscall" 10 | _ "unsafe" 11 | ) 12 | 13 | //go:linkname WSASendtoInet4 syscall.wsaSendtoInet4 14 | //go:noescape 15 | func WSASendtoInet4(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *syscall.SockaddrInet4, overlapped *syscall.Overlapped, croutine *byte) (err error) 16 | 17 | //go:linkname WSASendtoInet6 syscall.wsaSendtoInet6 18 | //go:noescape 19 | func WSASendtoInet6(s syscall.Handle, bufs *syscall.WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *syscall.SockaddrInet6, overlapped *syscall.Overlapped, croutine *byte) (err error) 20 | 21 | const ( 22 | SIO_TCP_INITIAL_RTO = syscall.IOC_IN | syscall.IOC_VENDOR | 17 23 | TCP_INITIAL_RTO_UNSPECIFIED_RTT = ^uint16(0) 24 | TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS = ^uint8(1) 25 | ) 26 | 27 | type TCP_INITIAL_RTO_PARAMETERS struct { 28 | Rtt uint16 29 | MaxSynRetransmissions uint8 30 | } 31 | 32 | var Support_TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS = sync.OnceValue(func() bool { 33 | var maj, min, build uint32 34 | rtlGetNtVersionNumbers(&maj, &min, &build) 35 | return maj >= 10 && build&0xffff >= 16299 36 | }) 37 | 38 | //go:linkname rtlGetNtVersionNumbers syscall.rtlGetNtVersionNumbers 39 | //go:noescape 40 | func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) 41 | -------------------------------------------------------------------------------- /internal/internals/syscall/windows/psapi_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package windows 6 | 7 | type PROCESS_MEMORY_COUNTERS struct { 8 | CB uint32 9 | PageFaultCount uint32 10 | PeakWorkingSetSize uintptr 11 | WorkingSetSize uintptr 12 | QuotaPeakPagedPoolUsage uintptr 13 | QuotaPagedPoolUsage uintptr 14 | QuotaPeakNonPagedPoolUsage uintptr 15 | QuotaNonPagedPoolUsage uintptr 16 | PagefileUsage uintptr 17 | PeakPagefileUsage uintptr 18 | } 19 | 20 | //sys GetProcessMemoryInfo(handle syscall.Handle, memCounters *PROCESS_MEMORY_COUNTERS, cb uint32) (err error) = psapi.GetProcessMemoryInfo 21 | -------------------------------------------------------------------------------- /internal/internals/syscall/windows/reparse_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package windows 6 | 7 | import ( 8 | "syscall" 9 | "unsafe" 10 | ) 11 | 12 | const ( 13 | FSCTL_SET_REPARSE_POINT = 0x000900A4 14 | IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 15 | IO_REPARSE_TAG_DEDUP = 0x80000013 16 | 17 | SYMLINK_FLAG_RELATIVE = 1 18 | ) 19 | 20 | // These structures are described 21 | // in https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/ca069dad-ed16-42aa-b057-b6b207f447cc 22 | // and https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/b41f1cbf-10df-4a47-98d4-1c52a833d913. 23 | 24 | type REPARSE_DATA_BUFFER struct { 25 | ReparseTag uint32 26 | ReparseDataLength uint16 27 | Reserved uint16 28 | DUMMYUNIONNAME byte 29 | } 30 | 31 | // REPARSE_DATA_BUFFER_HEADER is a common part of REPARSE_DATA_BUFFER structure. 32 | type REPARSE_DATA_BUFFER_HEADER struct { 33 | ReparseTag uint32 34 | // The size, in bytes, of the reparse data that follows 35 | // the common portion of the REPARSE_DATA_BUFFER element. 36 | // This value is the length of the data starting at the 37 | // SubstituteNameOffset field. 38 | ReparseDataLength uint16 39 | Reserved uint16 40 | } 41 | 42 | type SymbolicLinkReparseBuffer struct { 43 | // The integer that contains the offset, in bytes, 44 | // of the substitute name string in the PathBuffer array, 45 | // computed as an offset from byte 0 of PathBuffer. Note that 46 | // this offset must be divided by 2 to get the array index. 47 | SubstituteNameOffset uint16 48 | // The integer that contains the length, in bytes, of the 49 | // substitute name string. If this string is null-terminated, 50 | // SubstituteNameLength does not include the Unicode null character. 51 | SubstituteNameLength uint16 52 | // PrintNameOffset is similar to SubstituteNameOffset. 53 | PrintNameOffset uint16 54 | // PrintNameLength is similar to SubstituteNameLength. 55 | PrintNameLength uint16 56 | // Flags specifies whether the substitute name is a full path name or 57 | // a path name relative to the directory containing the symbolic link. 58 | Flags uint32 59 | PathBuffer [1]uint16 60 | } 61 | 62 | // Path returns path stored in rb. 63 | func (rb *SymbolicLinkReparseBuffer) Path() string { 64 | n1 := rb.SubstituteNameOffset / 2 65 | n2 := (rb.SubstituteNameOffset + rb.SubstituteNameLength) / 2 66 | return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rb.PathBuffer[0]))[n1:n2:n2]) 67 | } 68 | 69 | type MountPointReparseBuffer struct { 70 | // The integer that contains the offset, in bytes, 71 | // of the substitute name string in the PathBuffer array, 72 | // computed as an offset from byte 0 of PathBuffer. Note that 73 | // this offset must be divided by 2 to get the array index. 74 | SubstituteNameOffset uint16 75 | // The integer that contains the length, in bytes, of the 76 | // substitute name string. If this string is null-terminated, 77 | // SubstituteNameLength does not include the Unicode null character. 78 | SubstituteNameLength uint16 79 | // PrintNameOffset is similar to SubstituteNameOffset. 80 | PrintNameOffset uint16 81 | // PrintNameLength is similar to SubstituteNameLength. 82 | PrintNameLength uint16 83 | PathBuffer [1]uint16 84 | } 85 | 86 | // Path returns path stored in rb. 87 | func (rb *MountPointReparseBuffer) Path() string { 88 | n1 := rb.SubstituteNameOffset / 2 89 | n2 := (rb.SubstituteNameOffset + rb.SubstituteNameLength) / 2 90 | return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(&rb.PathBuffer[0]))[n1:n2:n2]) 91 | } 92 | -------------------------------------------------------------------------------- /internal/internals/syscall/windows/symlink_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package windows 6 | 7 | import "syscall" 8 | 9 | const ( 10 | ERROR_INVALID_PARAMETER syscall.Errno = 87 11 | 12 | FILE_SUPPORTS_OPEN_BY_FILE_ID = 0x01000000 13 | 14 | // symlink support for CreateSymbolicLink() starting with Windows 10 (1703, v10.0.14972) 15 | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x2 16 | 17 | // FileInformationClass values 18 | FileBasicInfo = 0 // FILE_BASIC_INFO 19 | FileStandardInfo = 1 // FILE_STANDARD_INFO 20 | FileNameInfo = 2 // FILE_NAME_INFO 21 | FileStreamInfo = 7 // FILE_STREAM_INFO 22 | FileCompressionInfo = 8 // FILE_COMPRESSION_INFO 23 | FileAttributeTagInfo = 9 // FILE_ATTRIBUTE_TAG_INFO 24 | FileIdBothDirectoryInfo = 0xa // FILE_ID_BOTH_DIR_INFO 25 | FileIdBothDirectoryRestartInfo = 0xb // FILE_ID_BOTH_DIR_INFO 26 | FileRemoteProtocolInfo = 0xd // FILE_REMOTE_PROTOCOL_INFO 27 | FileFullDirectoryInfo = 0xe // FILE_FULL_DIR_INFO 28 | FileFullDirectoryRestartInfo = 0xf // FILE_FULL_DIR_INFO 29 | FileStorageInfo = 0x10 // FILE_STORAGE_INFO 30 | FileAlignmentInfo = 0x11 // FILE_ALIGNMENT_INFO 31 | FileIdInfo = 0x12 // FILE_ID_INFO 32 | FileIdExtdDirectoryInfo = 0x13 // FILE_ID_EXTD_DIR_INFO 33 | FileIdExtdDirectoryRestartInfo = 0x14 // FILE_ID_EXTD_DIR_INFO 34 | ) 35 | 36 | type FILE_ATTRIBUTE_TAG_INFO struct { 37 | FileAttributes uint32 38 | ReparseTag uint32 39 | } 40 | 41 | //sys GetFileInformationByHandleEx(handle syscall.Handle, class uint32, info *byte, bufsize uint32) (err error) 42 | -------------------------------------------------------------------------------- /internal/internals/syscall/windows/sysdll/sysdll.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build windows 6 | 7 | // Package sysdll is an internal leaf package that records and reports 8 | // which Windows DLL names are used by Go itself. These DLLs are then 9 | // only loaded from the System32 directory. See Issue 14959. 10 | package sysdll 11 | 12 | // IsSystemDLL reports whether the named dll key (a base name, like 13 | // "foo.dll") is a system DLL which should only be loaded from the 14 | // Windows SYSTEM32 directory. 15 | // 16 | // Filenames are case sensitive, but that doesn't matter because 17 | // the case registered with Add is also the same case used with 18 | // LoadDLL later. 19 | // 20 | // It has no associated mutex and should only be mutated serially 21 | // (currently: during init), and not concurrent with DLL loading. 22 | var IsSystemDLL = map[string]bool{} 23 | 24 | // Add notes that dll is a system32 DLL which should only be loaded 25 | // from the Windows SYSTEM32 directory. It returns its argument back, 26 | // for ease of use in generated code. 27 | func Add(dll string) string { 28 | IsSystemDLL[dll] = true 29 | return dll 30 | } 31 | -------------------------------------------------------------------------------- /internal/internals/trace/traceviewer/format/format.go: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package traceviewer provides definitions of the JSON data structures 6 | // used by the Chrome trace viewer. 7 | // 8 | // The official description of the format is in this file: 9 | // https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview 10 | // 11 | // Note: This can't be part of the parent traceviewer package as that would 12 | // throw. go_bootstrap cannot depend on the cgo version of package net in ./make.bash. 13 | package format 14 | 15 | type Data struct { 16 | Events []*Event `json:"traceEvents"` 17 | Frames map[string]Frame `json:"stackFrames"` 18 | TimeUnit string `json:"displayTimeUnit"` 19 | } 20 | 21 | type Event struct { 22 | Name string `json:"name,omitempty"` 23 | Phase string `json:"ph"` 24 | Scope string `json:"s,omitempty"` 25 | Time float64 `json:"ts"` 26 | Dur float64 `json:"dur,omitempty"` 27 | PID uint64 `json:"pid"` 28 | TID uint64 `json:"tid"` 29 | ID uint64 `json:"id,omitempty"` 30 | BindPoint string `json:"bp,omitempty"` 31 | Stack int `json:"sf,omitempty"` 32 | EndStack int `json:"esf,omitempty"` 33 | Arg any `json:"args,omitempty"` 34 | Cname string `json:"cname,omitempty"` 35 | Category string `json:"cat,omitempty"` 36 | } 37 | 38 | type Frame struct { 39 | Name string `json:"name"` 40 | Parent int `json:"parent,omitempty"` 41 | } 42 | 43 | type NameArg struct { 44 | Name string `json:"name"` 45 | } 46 | 47 | type BlockedArg struct { 48 | Blocked string `json:"blocked"` 49 | } 50 | 51 | type SortIndexArg struct { 52 | Index int `json:"sort_index"` 53 | } 54 | 55 | type HeapCountersArg struct { 56 | Allocated uint64 57 | NextGC uint64 58 | } 59 | 60 | const ( 61 | ProcsSection = 0 // where Goroutines or per-P timelines are presented. 62 | StatsSection = 1 // where counters are presented. 63 | TasksSection = 2 // where Task hierarchy & timeline is presented. 64 | ) 65 | 66 | type GoroutineCountersArg struct { 67 | Running uint64 68 | Runnable uint64 69 | GCWaiting uint64 70 | } 71 | 72 | type ThreadCountersArg struct { 73 | Running int64 74 | InSyscall int64 75 | } 76 | 77 | type ThreadIDArg struct { 78 | ThreadID uint64 79 | } 80 | -------------------------------------------------------------------------------- /internal/version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | var ( 4 | version = "v0.0.0-devel" 5 | ) 6 | 7 | func Version() string { 8 | return version 9 | } 10 | -------------------------------------------------------------------------------- /pkg/cli/interface.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import "context" 4 | 5 | type Command interface { 6 | Naming() *Name 7 | Run(ctx context.Context, args []string) error 8 | } 9 | 10 | type CanPreRun interface { 11 | PreRun(ctx context.Context) context.Context 12 | } 13 | -------------------------------------------------------------------------------- /pkg/cli/name.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type Name struct { 9 | Name string 10 | Desc string 11 | ValidArgs ValidArgs 12 | 13 | subcommands []Command 14 | parent Command 15 | } 16 | 17 | func (n *Name) Naming() *Name { 18 | return n 19 | } 20 | 21 | func (n *Name) Add(c Command) { 22 | n.subcommands = append(n.subcommands, c) 23 | } 24 | 25 | func ParseValidArgs(s string) ValidArgs { 26 | if s == "" { 27 | return ValidArgs{} 28 | } 29 | 30 | v := make(ValidArgs, 0) 31 | 32 | args := strings.Split(s, " ") 33 | 34 | for i := range args { 35 | arg := strings.TrimSpace(args[i]) 36 | v = append(v, arg) 37 | } 38 | 39 | return v 40 | } 41 | 42 | type ValidArgs []string 43 | 44 | func (as ValidArgs) HasVariadic() bool { 45 | for _, a := range as { 46 | if strings.HasSuffix(a, "...") { 47 | return true 48 | } 49 | } 50 | return false 51 | } 52 | 53 | func (as ValidArgs) Validate(args []string) error { 54 | if as.HasVariadic() { 55 | if len(args) < len(as) { 56 | return fmt.Errorf("requires at least %d arg(s), only received %d", len(as), len(args)) 57 | } 58 | return nil 59 | } 60 | if len(as) != len(args) { 61 | return fmt.Errorf("accepts %d arg(s), received %d", len(as), len(args)) 62 | } 63 | return nil 64 | 65 | } 66 | -------------------------------------------------------------------------------- /pkg/cueify/core/util.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | encodingjson "encoding/json" 5 | "reflect" 6 | "sort" 7 | "strconv" 8 | "strings" 9 | "unicode" 10 | 11 | cueast "cuelang.org/go/cue/ast" 12 | "cuelang.org/go/cue/literal" 13 | cuetoken "cuelang.org/go/cue/token" 14 | "cuelang.org/go/encoding/json" 15 | ) 16 | 17 | func SafeIdentifierFromImportPath(s string) string { 18 | parts := strings.Split(s, "/") 19 | 20 | lastIdx := len(parts) 21 | 22 | // 23 | for { 24 | lastIdx = lastIdx - 1 25 | 26 | if lastIdx < 0 { 27 | continue 28 | } 29 | 30 | last := parts[lastIdx] 31 | 32 | // drop version in path 33 | last = strings.Split(last, "@")[0] 34 | 35 | // use parent when /v2 36 | if len(last) > 2 && last[0] == 'v' { 37 | // v2 38 | if i, err := strconv.ParseInt(last[0:], 10, 64); err == nil && i > 1 { 39 | continue 40 | } 41 | } 42 | 43 | // use parent when number only 44 | if len(last) > 0 && unicode.IsNumber(rune(last[0])) { 45 | continue 46 | } 47 | 48 | runes := []rune(last) 49 | 50 | for i, r := range runes { 51 | if !unicode.IsLetter(r) && !unicode.IsDigit(r) && r != '_' { 52 | runes[i] = '_' 53 | } 54 | } 55 | 56 | return string(runes) 57 | } 58 | } 59 | 60 | func Extract(v interface{}) (cueast.Expr, error) { 61 | data, err := encodingjson.Marshal(v) 62 | if err != nil { 63 | return nil, err 64 | } 65 | return json.Extract("", data) 66 | } 67 | 68 | func ExtractWithType(v interface{}) (cueast.Expr, error) { 69 | switch x := v.(type) { 70 | case map[string]interface{}: 71 | if len(x) == 0 { 72 | return cueast.NewStruct(&cueast.Field{ 73 | Label: cueast.NewList(cueast.NewIdent("string")), 74 | Value: cueast.NewIdent("_"), 75 | }), nil 76 | } 77 | 78 | keys := make([]string, 0) 79 | for k := range x { 80 | keys = append(keys, k) 81 | } 82 | sort.Strings(keys) 83 | 84 | fields := make([]interface{}, len(keys)) 85 | 86 | for i, k := range keys { 87 | valueExpr, err := ExtractWithType(x[k]) 88 | if err != nil { 89 | return nil, err 90 | } 91 | fields[i] = &cueast.Field{ 92 | Label: cueast.NewString(k), 93 | Token: cuetoken.COLON, 94 | Optional: cuetoken.Blank.Pos(), 95 | Value: valueExpr, 96 | } 97 | } 98 | 99 | return cueast.NewStruct(fields...), nil 100 | case []interface{}: 101 | typ := cueast.Expr(cueast.NewIdent("_")) 102 | if len(x) > 0 { 103 | t, err := ExtractWithType(x[0]) 104 | if err != nil { 105 | return nil, err 106 | } 107 | typ = t 108 | } 109 | return cueast.NewList(&cueast.Ellipsis{Type: typ}), nil 110 | case nil: 111 | return cueast.NewIdent("_"), nil 112 | default: 113 | d, _ := encodingjson.Marshal(v) 114 | expr, err := json.Extract("", d) 115 | if err != nil { 116 | return nil, err 117 | } 118 | return defaultValueAndType( 119 | expr, 120 | cueast.NewIdent(reflect.TypeOf(v).String()), 121 | ), nil 122 | } 123 | } 124 | 125 | func defaultValueAndType(defaultValue cueast.Expr, t cueast.Expr) cueast.Expr { 126 | return cueast.NewBinExpr(cuetoken.OR, &cueast.UnaryExpr{Op: cuetoken.MUL, X: defaultValue}, t) 127 | } 128 | 129 | func NewTripleBytes(data []byte) *cueast.BasicLit { 130 | return &cueast.BasicLit{ 131 | Kind: cuetoken.STRING, 132 | ValuePos: cuetoken.NoPos, 133 | Value: "'''\n" + strings.Replace(string(data), "\\", "\\\\", -1) + "'''", 134 | } 135 | } 136 | 137 | func NewBytes(data []byte) *cueast.BasicLit { 138 | return &cueast.BasicLit{ 139 | Kind: cuetoken.STRING, 140 | ValuePos: cuetoken.NoPos, 141 | Value: literal.Bytes.Quote(string(data)), 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /pkg/cueify/crd/extractor_test.go: -------------------------------------------------------------------------------- 1 | package helm_test 2 | 3 | import ( 4 | "context" 5 | "os" 6 | "testing" 7 | 8 | "github.com/go-courier/logr" 9 | "github.com/go-courier/logr/slog" 10 | "github.com/octohelm/cuemod/pkg/cueify" 11 | "github.com/onsi/gomega" 12 | ) 13 | 14 | func TestExtractor(t *testing.T) { 15 | ctx := logr.WithLogger(context.Background(), slog.Logger(slog.Default())) 16 | 17 | _ = os.RemoveAll("./testdata/gen") 18 | 19 | err := cueify.ExtractToDir( 20 | ctx, 21 | "crd", 22 | "./testdata/src", 23 | "./testdata/gen", 24 | ) 25 | 26 | gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 27 | } 28 | -------------------------------------------------------------------------------- /pkg/cueify/crd/testdata/gen/.sum: -------------------------------------------------------------------------------- 1 | h1:+/o+DsKNjPPqY+8y0g36WKlPtllEfIfbpLhRHZFMSfg= -------------------------------------------------------------------------------- /pkg/cueify/golang/astutil.go: -------------------------------------------------------------------------------- 1 | package golang 2 | 3 | import ( 4 | "strconv" 5 | 6 | cueast "cuelang.org/go/cue/ast" 7 | cuetoken "cuelang.org/go/cue/token" 8 | ) 9 | 10 | func newInt(i int) *cueast.BasicLit { 11 | return cueast.NewLit(cuetoken.INT, strconv.Itoa(i)) 12 | } 13 | 14 | func oneOf(types ...cueast.Expr) cueast.Expr { 15 | return cueast.NewBinExpr(cuetoken.OR, types...) 16 | } 17 | 18 | func allOf(types ...cueast.Expr) cueast.Expr { 19 | return cueast.NewBinExpr(cuetoken.AND, types...) 20 | } 21 | 22 | func any() *cueast.Ident { 23 | return cueast.NewIdent("_") 24 | } 25 | 26 | func addComments(node cueast.Node, comments ...*cueast.CommentGroup) { 27 | for i := range comments { 28 | cg := comments[i] 29 | if cg == nil { 30 | continue 31 | } 32 | cueast.AddComment(node, comments[i]) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /pkg/cueify/golang/extractor.go: -------------------------------------------------------------------------------- 1 | package golang 2 | 3 | import ( 4 | "context" 5 | "go/build" 6 | "path/filepath" 7 | 8 | cueast "cuelang.org/go/cue/ast" 9 | "github.com/octohelm/cuemod/pkg/cueify/core" 10 | ) 11 | 12 | func init() { 13 | core.Register(&Extractor{}) 14 | } 15 | 16 | // Extractor similar to cue go, but just only generate for one import path 17 | // 18 | // Targets: 19 | // 20 | // * gen const values 21 | // * gen types 22 | // * k8s resources with meta_v1.TypeMeta should gen with { apiVersion, kind } 23 | // 24 | // Rules: 25 | // 26 | // * skip & drop imports from go std libs exclude cue builtins support. 27 | type Extractor struct { 28 | } 29 | 30 | func (Extractor) Name() string { 31 | return "go" 32 | } 33 | 34 | func (Extractor) Detect(ctx context.Context, src string) (bool, map[string]string) { 35 | goFiles, err := filepath.Glob(filepath.Join(src, "*.go")) 36 | if err == nil { 37 | return len(goFiles) > 0, nil 38 | } 39 | return false, nil 40 | } 41 | 42 | func (e *Extractor) Extract(ctx context.Context, src string) ([]*cueast.File, error) { 43 | pkg, err := build.ImportDir(src, build.IgnoreVendor) 44 | if err != nil { 45 | return nil, err 46 | } 47 | return (&pkgExtractor{Package: pkg}).Extract(ctx) 48 | } 49 | -------------------------------------------------------------------------------- /pkg/cueify/golang/extractor_test.go: -------------------------------------------------------------------------------- 1 | package golang_test 2 | 3 | import ( 4 | "context" 5 | "os" 6 | "testing" 7 | 8 | "github.com/go-courier/logr/slog" 9 | 10 | "github.com/octohelm/cuemod/pkg/cueify" 11 | 12 | "github.com/go-courier/logr" 13 | "github.com/onsi/gomega" 14 | ) 15 | 16 | func TestExtractor(t *testing.T) { 17 | ctx := logr.WithLogger(context.Background(), slog.Logger(slog.Default())) 18 | 19 | _ = os.RemoveAll("./testdata/gen") 20 | 21 | err := cueify.ExtractToDir( 22 | ctx, 23 | "go", 24 | "./testdata/src", 25 | "./testdata/gen", 26 | ) 27 | 28 | gomega.NewWithT(t).Expect(err).To(gomega.BeNil()) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/cueify/golang/fake_importer.go: -------------------------------------------------------------------------------- 1 | package golang 2 | 3 | import ( 4 | "go/importer" 5 | "go/types" 6 | "regexp" 7 | "strings" 8 | ) 9 | 10 | func newFakeImporter() types.Importer { 11 | return &fakeImporter{Importer: importer.Default()} 12 | } 13 | 14 | type fakeImporter struct { 15 | Importer types.Importer 16 | } 17 | 18 | func (f *fakeImporter) Import(importPath string) (*types.Package, error) { 19 | if pkg, err := f.Importer.Import(importPath); err == nil { 20 | return pkg, nil 21 | } 22 | 23 | pkg := types.NewPackage(importPath, pkgNameFromImportPath(importPath)) 24 | pkg.MarkComplete() 25 | return pkg, nil 26 | } 27 | 28 | var reV = regexp.MustCompile("v([0-9]+)$") 29 | 30 | // pkg name from import path 31 | func pkgNameFromImportPath(importPath string) string { 32 | parts := strings.Split(importPath, "/") 33 | name := parts[len(parts)-1] 34 | 35 | // xxx/v2 36 | if len(parts) > 1 && reV.MatchString(name) && !(name == "v1" || name == "v0") { 37 | name = parts[len(parts)-2] 38 | } 39 | 40 | // like yaml.v2 41 | if names := strings.Split(name, "."); len(names) == 2 { 42 | if reV.MatchString(names[1]) { 43 | name = names[0] 44 | } 45 | } 46 | 47 | return name 48 | } 49 | -------------------------------------------------------------------------------- /pkg/cueify/golang/func_method.go: -------------------------------------------------------------------------------- 1 | package golang 2 | 3 | import "go/types" 4 | 5 | var stringInterfaces = map[string]method{ 6 | "MarshalText": { 7 | Results: []string{"[]byte", "error"}, 8 | }, 9 | "UnmarshalText": { 10 | PtrRecv: true, 11 | Params: []string{"[]byte"}, 12 | Results: []string{"error"}, 13 | }, 14 | } 15 | 16 | var topInterfaces = map[string]method{ 17 | "MarshalJSON": { 18 | Results: []string{"[]byte", "error"}, 19 | }, 20 | "UnmarshalJSON": { 21 | PtrRecv: true, 22 | Params: []string{"[]byte"}, 23 | Results: []string{"error"}, 24 | }, 25 | "MarshalYAML": { 26 | Results: []string{"interface{}", "error"}, 27 | }, 28 | "UnmarshalYAML": { 29 | PtrRecv: true, 30 | Params: []string{"interface{}"}, 31 | Results: []string{"error"}, 32 | }, 33 | } 34 | 35 | type method struct { 36 | PtrRecv bool 37 | Params []string 38 | Results []string 39 | } 40 | 41 | func (m *method) Equal(fn *types.Func) bool { 42 | s := fn.Type().(*types.Signature) 43 | 44 | if m.PtrRecv { 45 | if _, ok := s.Recv().Type().(*types.Pointer); !ok { 46 | return false 47 | } 48 | } 49 | 50 | params := s.Params() 51 | results := s.Results() 52 | 53 | paramsLen := params.Len() 54 | resultsLen := results.Len() 55 | 56 | if paramsLen != len(m.Params) || resultsLen != len(m.Results) { 57 | return false 58 | } 59 | 60 | for i := 0; i < paramsLen; i++ { 61 | if params.At(i).Type().String() != m.Params[i] { 62 | return false 63 | } 64 | } 65 | 66 | for i := 0; i < resultsLen; i++ { 67 | if results.At(i).Type().String() != m.Results[i] { 68 | return false 69 | } 70 | } 71 | 72 | return true 73 | } 74 | -------------------------------------------------------------------------------- /pkg/cueify/golang/group_version.go: -------------------------------------------------------------------------------- 1 | package golang 2 | 3 | import ( 4 | "context" 5 | 6 | "k8s.io/apimachinery/pkg/runtime/schema" 7 | ) 8 | 9 | type contextGroupVersionKind struct { 10 | } 11 | 12 | func groupVersionKindFromContext(ctx context.Context) *schema.GroupVersionKind { 13 | if i, ok := ctx.Value(contextGroupVersionKind{}).(*schema.GroupVersionKind); ok { 14 | return i 15 | } 16 | return nil 17 | } 18 | 19 | func withGroupVersionKind(ctx context.Context, i *schema.GroupVersionKind) context.Context { 20 | return context.WithValue(ctx, contextGroupVersionKind{}, i) 21 | } 22 | -------------------------------------------------------------------------------- /pkg/cueify/golang/import_paths.go: -------------------------------------------------------------------------------- 1 | package golang 2 | 3 | import ( 4 | "context" 5 | "regexp" 6 | 7 | cueast "cuelang.org/go/cue/ast" 8 | ) 9 | 10 | type importPaths map[string]string 11 | 12 | func (i importPaths) toImportDecl() *cueast.ImportDecl { 13 | importDecl := &cueast.ImportDecl{} 14 | 15 | for importPath := range i { 16 | importDecl.Specs = append(importDecl.Specs, cueast.NewImport(cueast.NewIdent(i[importPath]), importPath)) 17 | } 18 | 19 | return importDecl 20 | } 21 | 22 | var invalidToken = regexp.MustCompile(`[^A-Za-z0-9_]`) 23 | 24 | func (i importPaths) add(importPath string) string { 25 | i[importPath] = "pkg_" + invalidToken.ReplaceAllString(importPath, "_") 26 | return i[importPath] 27 | } 28 | 29 | type contextImportPaths struct { 30 | } 31 | 32 | func importPathsFromContext(ctx context.Context) importPaths { 33 | if i, ok := ctx.Value(contextImportPaths{}).(importPaths); ok { 34 | return i 35 | } 36 | return importPaths{} 37 | } 38 | 39 | func withImportPaths(ctx context.Context, i importPaths) context.Context { 40 | return context.WithValue(ctx, contextImportPaths{}, i) 41 | } 42 | -------------------------------------------------------------------------------- /pkg/cueify/golang/std/list.go: -------------------------------------------------------------------------------- 1 | //go:generate sh ./list.sh 2 | package std 3 | 4 | import ( 5 | "bufio" 6 | "bytes" 7 | _ "embed" 8 | ) 9 | 10 | //go:embed list.txt 11 | var list []byte 12 | 13 | var stds = map[string]bool{} 14 | 15 | func init() { 16 | scanner := bufio.NewScanner(bytes.NewBuffer(list)) 17 | for scanner.Scan() { 18 | pkg := scanner.Text() 19 | if pkg != "" { 20 | stds[pkg] = true 21 | } 22 | } 23 | } 24 | 25 | func IsStd(importPath string) bool { 26 | if _, ok := stds[importPath]; ok { 27 | return true 28 | } 29 | return false 30 | } 31 | -------------------------------------------------------------------------------- /pkg/cueify/golang/std/list.sh: -------------------------------------------------------------------------------- 1 | go list std > ./list.txt 2 | exit 0 -------------------------------------------------------------------------------- /pkg/cueify/golang/testdata/gen/.sum: -------------------------------------------------------------------------------- 1 | h1:oREO0X5CZ2uH79+2HyQJq13XrYugkVtEOVBk26tXjBE= -------------------------------------------------------------------------------- /pkg/cueify/golang/testdata/gen/enums_go_gen.cue: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT THIS FILE DIRECTLY. 2 | // generated by go extractor. 3 | package src 4 | 5 | #Protocol: #FTP | #HTTP 6 | 7 | #HTTP: "HTTP" 8 | #FTP: "FTP" 9 | -------------------------------------------------------------------------------- /pkg/cueify/golang/testdata/gen/types_go_gen.cue: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT THIS FILE DIRECTLY. 2 | // generated by go extractor. 3 | package src 4 | 5 | import pkg_time "time" 6 | 7 | #Alias: #FTP | #HTTP 8 | 9 | #String: string 10 | 11 | #Map: [#Protocol]: string 12 | 13 | #MapAny: [string]: _ 14 | 15 | #Bytes: bytes 16 | 17 | #Slice: [...string] 18 | 19 | #Array: 2 * [#String] 20 | 21 | #Any: _ 22 | 23 | // struct comment 24 | #Struct: { 25 | #Sub 26 | 27 | // name 28 | // name 29 | name: string 30 | } 31 | 32 | #Sub: { 33 | pkg_time.Time 34 | optional?: uint64 35 | nullable: null | int 36 | } 37 | 38 | #Strfmt: string 39 | 40 | #YAML: _ 41 | -------------------------------------------------------------------------------- /pkg/cueify/golang/testdata/gen/values_go_gen.cue: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT THIS FILE DIRECTLY. 2 | // generated by go extractor. 3 | package src 4 | 5 | // test 6 | #StringValue: "some str" // test2 7 | #BoolValue: true 8 | 9 | #IntValue: 1 10 | #IntValue2: 2 11 | 12 | #Rename: "Mon Jan _2 15:04:05 2006" 13 | -------------------------------------------------------------------------------- /pkg/cueify/golang/testdata/src/enums.go: -------------------------------------------------------------------------------- 1 | package src 2 | 3 | type Protocol string 4 | 5 | const ( 6 | HTTP Protocol = "HTTP" 7 | FTP Protocol = "FTP" 8 | ) 9 | -------------------------------------------------------------------------------- /pkg/cueify/golang/testdata/src/types.go: -------------------------------------------------------------------------------- 1 | package src 2 | 3 | import ( 4 | "sync" 5 | "time" 6 | ) 7 | 8 | type Alias = Protocol 9 | 10 | type String string 11 | 12 | type Map map[Protocol]string 13 | 14 | type MapAny map[string]any 15 | 16 | type Bytes []byte 17 | 18 | type Slice []string 19 | 20 | type Array [2]String 21 | 22 | type Any interface{} 23 | 24 | type private string 25 | 26 | // struct comment 27 | type Struct struct { 28 | Sub 29 | // name 30 | // name 31 | Name string `json:"name"` 32 | } 33 | 34 | type Sub struct { 35 | time.Time 36 | 37 | // should ignore 38 | sync.Mutex 39 | 40 | Optional *uint64 `json:"optional,omitempty"` 41 | Nullable *int `json:"nullable"` 42 | } 43 | 44 | type Strfmt struct{} 45 | 46 | func (Strfmt) MarshalText() (text []byte, err error) { 47 | return []byte("="), nil 48 | } 49 | 50 | func (*Strfmt) UnmarshalText(text []byte) (err error) { 51 | return nil 52 | } 53 | 54 | type YAML struct{} 55 | 56 | func (YAML) MarshalYAML() (data interface{}, err error) { 57 | return []byte("="), nil 58 | } 59 | -------------------------------------------------------------------------------- /pkg/cueify/golang/testdata/src/values.go: -------------------------------------------------------------------------------- 1 | package src 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | const ( 8 | // test 9 | StringValue = "some str" // test2 10 | BoolValue = true 11 | ) 12 | 13 | const ( 14 | IntValue int = iota + 1 15 | IntValue2 16 | ) 17 | 18 | const Rename = time.ANSIC 19 | -------------------------------------------------------------------------------- /pkg/cueify/register.go: -------------------------------------------------------------------------------- 1 | package cueify 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/octohelm/cuemod/pkg/cueify/core" 7 | _ "github.com/octohelm/cuemod/pkg/cueify/crd" 8 | _ "github.com/octohelm/cuemod/pkg/cueify/golang" 9 | ) 10 | 11 | func Detect(ctx context.Context, src string) (string, map[string]string) { 12 | return core.SharedExtractors.Detect(ctx, src) 13 | } 14 | 15 | func ExtractToDir(ctx context.Context, name string, src string, dist string) error { 16 | return core.SharedExtractors.ExtractToDir(ctx, name, src, dist) 17 | } 18 | -------------------------------------------------------------------------------- /pkg/cuemod/build.go: -------------------------------------------------------------------------------- 1 | package cuemod 2 | 3 | import ( 4 | "path/filepath" 5 | "strconv" 6 | "strings" 7 | 8 | cueast "cuelang.org/go/cue/ast" 9 | "cuelang.org/go/cue/build" 10 | "cuelang.org/go/cue/load" 11 | "cuelang.org/go/cue/parser" 12 | "github.com/octohelm/cuemod/pkg/cuemod/builtin" 13 | ) 14 | 15 | type OptionFunc = func(c *load.Config) 16 | 17 | func OptRoot(dir string) OptionFunc { 18 | return func(c *load.Config) { 19 | c.Dir = dir 20 | } 21 | } 22 | 23 | func OptOverlay(overlay map[string]load.Source) OptionFunc { 24 | return func(c *load.Config) { 25 | c.Overlay = overlay 26 | } 27 | } 28 | 29 | type ImportFunc = func(importPath string, importedAt string) (resolvedDir string, err error) 30 | 31 | func OptImportFunc(importFunc ImportFunc) OptionFunc { 32 | return func(c *load.Config) { 33 | c.ParseFile = func(filename string, src any) (*cueast.File, error) { 34 | f, err := parser.ParseFile(filename, src, parser.ParseComments) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | for i := range f.Imports { 40 | importPath, _ := strconv.Unquote(f.Imports[i].Path.Value) 41 | 42 | // skip abs path and rel path 43 | if filepath.IsAbs(importPath) { 44 | continue 45 | } 46 | 47 | // "xxx/xxxx:xxx" 48 | importPath = strings.Split(importPath, ":")[0] 49 | 50 | // skip builtin 51 | if builtin.IsBuiltIn(importPath) { 52 | continue 53 | } 54 | 55 | _, err := importFunc(importPath, filename) 56 | if err != nil { 57 | return nil, err 58 | } 59 | } 60 | 61 | return f, nil 62 | } 63 | } 64 | } 65 | 66 | type Instance = build.Instance 67 | 68 | func BuildConfig(optionFns ...OptionFunc) *load.Config { 69 | c := &load.Config{} 70 | for i := range optionFns { 71 | optionFns[i](c) 72 | } 73 | return c 74 | } 75 | 76 | func BuildInstances(c *load.Config, inputs []string) []*Instance { 77 | files := make([]string, len(inputs)) 78 | 79 | for i, f := range inputs { 80 | if filepath.IsAbs(f) { 81 | rel, _ := filepath.Rel(c.Dir, f) 82 | files[i] = "./" + rel 83 | } else { 84 | files[i] = f 85 | } 86 | } 87 | 88 | return load.Instances(files, c) 89 | } 90 | 91 | func Build(inputs []string, optionFns ...OptionFunc) *Instance { 92 | c := BuildConfig(optionFns...) 93 | // load only support related path 94 | return BuildInstances(c, inputs)[0] 95 | } 96 | -------------------------------------------------------------------------------- /pkg/cuemod/builtin/builtins.go: -------------------------------------------------------------------------------- 1 | package builtin 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | _ "embed" 7 | ) 8 | 9 | //go:embed builtins.txt 10 | var list []byte 11 | 12 | var builtins = map[string]bool{} 13 | 14 | func init() { 15 | scanner := bufio.NewScanner(bytes.NewBuffer(list)) 16 | for scanner.Scan() { 17 | importPath := scanner.Text() 18 | if importPath != "" { 19 | builtins[importPath] = true 20 | } 21 | } 22 | } 23 | 24 | func IsBuiltIn(importPath string) bool { 25 | if _, ok := builtins[importPath]; ok { 26 | return true 27 | } 28 | return false 29 | } 30 | -------------------------------------------------------------------------------- /pkg/cuemod/builtin/builtins.txt: -------------------------------------------------------------------------------- 1 | crypto/ed25519 2 | crypto/hmac 3 | crypto/md5 4 | crypto/sha1 5 | crypto/sha256 6 | crypto/sha512 7 | encoding/base64 8 | encoding/csv 9 | encoding/hex 10 | encoding/json 11 | encoding/yaml 12 | html 13 | list 14 | math 15 | math/bits 16 | net 17 | path 18 | regexp 19 | strconv 20 | strings 21 | struct 22 | text/tabwriter 23 | text/template 24 | time 25 | tool 26 | tool/cli 27 | tool/exec 28 | tool/file 29 | tool/http 30 | tool/os 31 | uuid -------------------------------------------------------------------------------- /pkg/cuemod/builtin/builtins_test.go: -------------------------------------------------------------------------------- 1 | package builtin 2 | 3 | import ( 4 | "go/build" 5 | "os" 6 | "strings" 7 | "testing" 8 | 9 | _ "cuelang.org/go/pkg" 10 | ) 11 | 12 | func TestGen(t *testing.T) { 13 | pkg, _ := build.Import("cuelang.org/go/pkg", "", build.ImportComment) 14 | 15 | list := make([]string, 0) 16 | 17 | for _, importPath := range pkg.Imports { 18 | if strings.HasPrefix(importPath, "cuelang.org/go/pkg/") { 19 | list = append(list, importPath[len("cuelang.org/go/pkg/"):]) 20 | } 21 | } 22 | 23 | _ = os.WriteFile("builtins.txt", []byte(strings.Join(list, "\n")), os.ModePerm) 24 | } 25 | -------------------------------------------------------------------------------- /pkg/cuemod/context_test.go: -------------------------------------------------------------------------------- 1 | package cuemod_test 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | "testing" 9 | 10 | "github.com/go-courier/logr/slog" 11 | 12 | "github.com/go-courier/logr" 13 | "github.com/octohelm/cuemod/pkg/cuemod" 14 | "github.com/octohelm/cuemod/pkg/cuemodx" 15 | "github.com/octohelm/cuemod/pkg/cuex" 16 | "github.com/octohelm/cuemod/pkg/cuex/format" 17 | . "github.com/onsi/gomega" 18 | 19 | _ "github.com/octohelm/cuemod/pkg/cuemod/testdata/embedstdlib" 20 | ) 21 | 22 | func TestContext(t *testing.T) { 23 | cwd, _ := os.Getwd() 24 | 25 | ctx := logr.WithLogger(context.Background(), slog.Logger(slog.Default())) 26 | ctx = cuemod.WithOpts(ctx, cuemod.OptVerbose(true)) 27 | 28 | t.Run("mod a", func(t *testing.T) { 29 | r := cuemod.ContextFor(filepath.Join(cwd, "./testdata/a")) 30 | _ = r.Cleanup() 31 | 32 | t.Run("EvalContext", func(t *testing.T) { 33 | data, err := cuemodx.EvalContext(ctx, r, ".", cuex.WithEncoding(cuex.JSON)) 34 | NewWithT(t).Expect(err).To(BeNil()) 35 | fmt.Println(string(data)) 36 | NewWithT(t).Expect(r.Mod.Require["k8s.io/api"].Version).To(Equal("v0.24.1")) 37 | }) 38 | 39 | t.Run("EvalContext from exported single file", func(t *testing.T) { 40 | data, err := cuemodx.EvalContext(ctx, r, ".", cuex.WithEncoding(cuex.CUE)) 41 | NewWithT(t).Expect(err).To(BeNil()) 42 | 43 | _ = os.WriteFile("../../_output/debug.cue", data, os.ModePerm) 44 | 45 | inst, _ := cuex.InstanceFromRaw(data) 46 | ret, err := cuex.Eval(inst, cuex.WithEncoding(cuex.JSON)) 47 | NewWithT(t).Expect(err).To(BeNil()) 48 | fmt.Println(string(ret)) 49 | }) 50 | }) 51 | 52 | t.Run("mod b", func(t *testing.T) { 53 | r := cuemod.ContextFor(filepath.Join(cwd, "./testdata/b")) 54 | _ = r.Cleanup() 55 | 56 | t.Run("ListCue", func(t *testing.T) { 57 | t.Run("one dir", func(t *testing.T) { 58 | files, err := r.ListCue(".") 59 | 60 | NewWithT(t).Expect(err).To(BeNil()) 61 | NewWithT(t).Expect(files).To(HaveLen(1)) 62 | }) 63 | 64 | t.Run("all", func(t *testing.T) { 65 | files, err := r.ListCue("./...") 66 | 67 | NewWithT(t).Expect(err).To(BeNil()) 68 | NewWithT(t).Expect(len(files) > 0).To(BeTrue()) 69 | 70 | t.Run("Format", func(t *testing.T) { 71 | err := format.FormatFiles(ctx, files, format.FormatOpts{ 72 | ReplaceFile: true, 73 | PrintNames: true, 74 | }) 75 | NewWithT(t).Expect(err).To(BeNil()) 76 | }) 77 | }) 78 | }) 79 | 80 | t.Run("Get", func(t *testing.T) { 81 | err := r.Get(ctx, "./...") 82 | NewWithT(t).Expect(err).To(BeNil()) 83 | }) 84 | }) 85 | } 86 | -------------------------------------------------------------------------------- /pkg/cuemod/mod.go: -------------------------------------------------------------------------------- 1 | package cuemod 2 | 3 | import "github.com/octohelm/cuemod/pkg/cuemod/mod" 4 | 5 | type Mod = mod.Mod 6 | -------------------------------------------------------------------------------- /pkg/cuemod/mod/mod.go: -------------------------------------------------------------------------------- 1 | package mod 2 | 3 | import ( 4 | "context" 5 | "os" 6 | "path/filepath" 7 | 8 | "golang.org/x/mod/semver" 9 | 10 | "github.com/octohelm/cuemod/pkg/cuemod/modfile" 11 | "github.com/pkg/errors" 12 | ) 13 | 14 | type Mod struct { 15 | modfile.ModFile 16 | modfile.ModVersion 17 | 18 | // Repo where module in vcs root 19 | Repo string 20 | // SubPath mod local sub path 21 | SubPath string 22 | // Dir module absolute dir 23 | Dir string 24 | // Root means this import path is mod root 25 | Root bool 26 | // Sum repo absolute dir sum 27 | Sum string 28 | } 29 | 30 | func (m *Mod) ModuleRoot() string { 31 | if m.SubPath != "" { 32 | return filepath.Join(m.Module, m.SubPath) 33 | } 34 | return m.Module 35 | } 36 | 37 | func (m *Mod) String() string { 38 | if m.Version == "" { 39 | return m.Module + "@v0.0.0" 40 | } 41 | return m.Module + "@" + m.Version 42 | } 43 | 44 | func (m *Mod) LoadInfo(ctx context.Context) (bool, error) { 45 | if m.Dir == "" || m.Dir[0] != '/' { 46 | return false, nil 47 | } 48 | 49 | if _, err := os.Stat(m.Dir); os.IsNotExist(err) { 50 | return false, errors.Wrapf(err, "%s not found", m.Dir) 51 | } 52 | 53 | exists, err := modfile.LoadModFile(m.Dir, &m.ModFile) 54 | if err != nil { 55 | return false, err 56 | } 57 | 58 | if exists { 59 | // module name should be from module.cue 60 | m.Module = m.ModFile.Module 61 | m.Root = true 62 | } 63 | 64 | return exists, nil 65 | } 66 | 67 | func (m *Mod) Resolved() bool { 68 | return m.Dir != "" 69 | } 70 | 71 | func (m *Mod) SetRequire(module string, modVersion modfile.ModVersion, indirect bool) { 72 | if module == m.Module { 73 | return 74 | } 75 | 76 | if m.Require == nil { 77 | m.Require = map[string]modfile.Requirement{} 78 | } 79 | 80 | r := modfile.Requirement{} 81 | 82 | r.ModVersion = modVersion 83 | r.Indirect = indirect 84 | 85 | if currentRequire, ok := m.Require[module]; ok { 86 | // always using greater one 87 | if versionGreaterThan(currentRequire.Version, r.Version) { 88 | r.ModVersion = currentRequire.ModVersion 89 | } 90 | 91 | if r.Indirect { 92 | r.Indirect = currentRequire.Indirect 93 | } 94 | } 95 | 96 | m.Require[module] = r 97 | 98 | if currentReplace, ok := m.Replace[modfile.VersionedPathIdentity{Path: module}]; ok { 99 | if currentReplace.IsLocalReplace() || currentReplace.Import != "" { 100 | return 101 | } 102 | 103 | currentReplace.Version = r.ModVersion.Version 104 | m.Replace[modfile.VersionedPathIdentity{Path: module}] = currentReplace 105 | } 106 | } 107 | 108 | func (m *Mod) FixVersion(repo string, version string) string { 109 | if m.Require != nil { 110 | if r, ok := m.Require[repo]; ok { 111 | if r.VcsRef != "" && r.Version == "v0.0.0" { 112 | return r.VcsRef 113 | } 114 | return r.Version 115 | } 116 | } 117 | return version 118 | } 119 | 120 | func versionGreaterThan(v string, w string) bool { 121 | if w == "" { 122 | return false 123 | } 124 | return semver.Compare(v, w) > 0 125 | } 126 | -------------------------------------------------------------------------------- /pkg/cuemod/mod_resolver_test.go: -------------------------------------------------------------------------------- 1 | package cuemod 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/go-courier/logr/slog" 8 | 9 | "github.com/octohelm/cuemod/pkg/cuemod/modfile" 10 | 11 | "github.com/go-courier/logr" 12 | 13 | . "github.com/onsi/gomega" 14 | 15 | _ "github.com/octohelm/cuemod/pkg/cuemod/testdata/embedstdlib" 16 | ) 17 | 18 | func TestModResolver(t *testing.T) { 19 | ctx := logr.WithLogger(context.Background(), slog.Logger(slog.Default())) 20 | 21 | ctx = WithOpts(ctx, OptVerbose(true)) 22 | 23 | m := newModResolver() 24 | 25 | t.Run("should resolve stdlib", func(t *testing.T) { 26 | mod, err := m.Get(ctx, "std.x.io/a", modfile.ModVersion{VcsRef: "main"}) 27 | NewWithT(t).Expect(err).To(BeNil()) 28 | NewWithT(t).Expect(mod.Module).To(Equal("std.x.io")) 29 | NewWithT(t).Expect(mod.Repo).To(Equal("std.x.io")) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/cuemod/modfile/load_test.go: -------------------------------------------------------------------------------- 1 | package modfile 2 | 3 | import ( 4 | "testing" 5 | 6 | . "github.com/onsi/gomega" 7 | ) 8 | 9 | func TestLoadModFile(t *testing.T) { 10 | mod := ModFile{} 11 | 12 | _, err := LoadModFile("../testdata/b", &mod) 13 | 14 | NewWithT(t).Expect(err).To(BeNil()) 15 | NewWithT(t).Expect(mod.Module).To(Equal("github.com/x/b")) 16 | 17 | t.Log(mod.String()) 18 | } 19 | -------------------------------------------------------------------------------- /pkg/cuemod/modfile/path_may_with_version.go: -------------------------------------------------------------------------------- 1 | package modfile 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | func ParsePathMayWithVersion(v string) (*VersionedPathIdentity, error) { 9 | if len(v) == 0 { 10 | return nil, fmt.Errorf("invalid %s", v) 11 | } 12 | 13 | parts := strings.Split(v, "@") 14 | 15 | i := parts[0] 16 | 17 | if i != "" && i[0] == '.' { 18 | return &VersionedPathIdentity{Path: i}, nil 19 | } 20 | 21 | if len(parts) > 1 { 22 | vv := strings.Split(parts[1], "#") 23 | if len(vv) > 1 { 24 | return &VersionedPathIdentity{Path: i, ModVersion: ModVersion{ 25 | Version: vv[0], VcsRef: vv[1], 26 | }}, nil 27 | } 28 | return &VersionedPathIdentity{Path: i, ModVersion: ModVersion{ 29 | Version: vv[0], 30 | }}, nil 31 | } 32 | return &VersionedPathIdentity{Path: i}, nil 33 | 34 | } 35 | 36 | type VersionedPathIdentity struct { 37 | Path string 38 | ModVersion 39 | } 40 | 41 | func (r *VersionedPathIdentity) UnmarshalText(text []byte) error { 42 | rp, err := ParsePathMayWithVersion(string(text)) 43 | if err != nil { 44 | return err 45 | } 46 | *r = *rp 47 | return nil 48 | } 49 | 50 | func (r VersionedPathIdentity) MarshalText() (text []byte, err error) { 51 | return []byte(r.String()), nil 52 | } 53 | 54 | func (r VersionedPathIdentity) IsLocalReplace() bool { 55 | return len(r.Path) > 0 && r.Path[0] == '.' 56 | } 57 | 58 | func (r VersionedPathIdentity) String() string { 59 | if r.IsLocalReplace() { 60 | return r.Path 61 | } 62 | 63 | b := strings.Builder{} 64 | b.WriteString(r.Path) 65 | 66 | if r.Version != "" || r.VcsRef != "" { 67 | b.WriteString("@") 68 | b.WriteString(r.Version) 69 | 70 | if r.VcsRef != "" { 71 | b.WriteString("#") 72 | b.WriteString(r.VcsRef) 73 | } 74 | } 75 | return b.String() 76 | } 77 | -------------------------------------------------------------------------------- /pkg/cuemod/options.go: -------------------------------------------------------------------------------- 1 | package cuemod 2 | 3 | import "context" 4 | 5 | type Opts struct { 6 | Upgrade bool 7 | Verbose bool 8 | Import string 9 | } 10 | 11 | type OptFn = func(o *Opts) 12 | 13 | func OptUpgrade(b bool) OptFn { 14 | return func(o *Opts) { 15 | o.Upgrade = b 16 | } 17 | } 18 | 19 | func OptImport(b string) OptFn { 20 | return func(o *Opts) { 21 | o.Import = b 22 | } 23 | } 24 | 25 | func OptVerbose(v bool) OptFn { 26 | return func(o *Opts) { 27 | o.Verbose = v 28 | } 29 | } 30 | 31 | type contextKeyForOpts int 32 | 33 | func OptsFromContext(ctx context.Context) Opts { 34 | if o, ok := ctx.Value(contextKeyForOpts(0)).(Opts); ok { 35 | return o 36 | } 37 | return Opts{} 38 | } 39 | 40 | func WithOpts(ctx context.Context, fns ...OptFn) context.Context { 41 | o := OptsFromContext(ctx) 42 | 43 | for _, fn := range fns { 44 | if fn != nil { 45 | fn(&o) 46 | } 47 | } 48 | 49 | return context.WithValue(ctx, contextKeyForOpts(0), o) 50 | } 51 | -------------------------------------------------------------------------------- /pkg/cuemod/stdlib/stdlib.go: -------------------------------------------------------------------------------- 1 | package stdlib 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "io/fs" 8 | "os" 9 | "path/filepath" 10 | "strings" 11 | 12 | "github.com/octohelm/cuemod/pkg/cuemod/mod" 13 | "golang.org/x/mod/sumdb/dirhash" 14 | ) 15 | 16 | var stdlibs = map[string]*stdlib{} 17 | 18 | type stdlib struct { 19 | mod.Mod 20 | fs fs.ReadDirFS 21 | } 22 | 23 | func Register(dirFs fs.ReadDirFS, version string, pkgs ...string) { 24 | for _, p := range pkgs { 25 | m := &stdlib{} 26 | m.Repo = p 27 | m.Module = p 28 | m.Version = version 29 | m.Root = true 30 | m.fs = dirFs 31 | 32 | stdlibs[m.Repo] = m 33 | } 34 | } 35 | 36 | func RepoRootForImportPath(repo string) (string, bool) { 37 | for lib := range stdlibs { 38 | if isSubDirFor(repo, lib) { 39 | return lib, true 40 | } 41 | } 42 | return "", false 43 | } 44 | 45 | func Mount(ctx context.Context, importPath string, modRoot string) (*mod.Mod, error) { 46 | repo, ok := RepoRootForImportPath(importPath) 47 | if !ok { 48 | return nil, nil 49 | } 50 | 51 | noWrite := modRoot == "" 52 | if noWrite { 53 | modRoot = "" 54 | } 55 | 56 | for lib := range stdlibs { 57 | if isSubDirFor(repo, lib) { 58 | found := stdlibs[lib] 59 | 60 | m := found.Mod 61 | 62 | dirSum, err := HashDir(found.fs, ".", "", dirhash.DefaultHash) 63 | if err != nil { 64 | return nil, err 65 | } 66 | m.Sum = dirSum 67 | 68 | m.Dir = filepath.Join(modRoot, "cue.mod/pkg/.cuemod/std", fmt.Sprintf( 69 | "%s@%s-%s", 70 | m.Repo, 71 | m.Version, 72 | m.Sum, 73 | )) 74 | 75 | if !noWrite { 76 | if _, err := os.Stat(m.Dir); os.IsNotExist(err) { 77 | _ = os.MkdirAll(m.Dir, os.ModePerm) 78 | 79 | err := fs.WalkDir(found.fs, repo, func(path string, d fs.DirEntry, err error) error { 80 | tmpPath := filepath.Join(m.Dir, "."+strings.TrimPrefix(path, repo)) 81 | 82 | if d.IsDir() { 83 | _ = os.MkdirAll(tmpPath, os.ModePerm) 84 | } else { 85 | f, err := found.fs.Open(path) 86 | if err != nil { 87 | return err 88 | } 89 | defer f.Close() 90 | data, _ := io.ReadAll(f) 91 | if err = os.WriteFile(tmpPath, data, os.ModePerm); err != nil { 92 | return err 93 | } 94 | } 95 | 96 | return err 97 | }) 98 | 99 | if err != nil { 100 | return nil, err 101 | } 102 | } 103 | } 104 | 105 | return &m, nil 106 | } 107 | } 108 | 109 | return nil, nil 110 | } 111 | 112 | func isSubDirFor(targetpath string, root string) bool { 113 | targetpath = targetpath + "/" 114 | root = root + "/" 115 | return strings.HasPrefix(targetpath, root) 116 | } 117 | 118 | func HashDir(fs fs.ReadDirFS, dir string, prefix string, hash dirhash.Hash) (string, error) { 119 | files := make([]string, 0) 120 | 121 | if err := RangeFile(fs, dir, func(filename string) error { 122 | files = append(files, filepath.ToSlash(filepath.Join(prefix, filename))) 123 | return nil 124 | }); err != nil { 125 | return "", err 126 | } 127 | 128 | return hash(files, func(name string) (io.ReadCloser, error) { 129 | return fs.Open(filepath.Join(dir, strings.TrimPrefix(name, prefix))) 130 | }) 131 | } 132 | 133 | func RangeFile(f fs.ReadDirFS, root string, each func(filename string) error) error { 134 | return fs.WalkDir(f, root, func(path string, d fs.DirEntry, err error) error { 135 | if err != nil { 136 | return err 137 | } 138 | if d.IsDir() { 139 | return nil 140 | } 141 | rel := path 142 | if root != "" && root != "." { 143 | rel, _ = filepath.Rel(root, path) 144 | } 145 | return each(rel) 146 | }) 147 | 148 | } 149 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/a/cue.mod/.gitignore: -------------------------------------------------------------------------------- 1 | gen/ 2 | pkg/ 3 | module.sum -------------------------------------------------------------------------------- /pkg/cuemod/testdata/a/cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "github.com/x/a" 2 | 3 | require: { 4 | "github.com/octohelm/cuemod-versioned-example": "v0.0.0-20230822070100-38465a937b3c" 5 | "github.com/octohelm/cuemod-versioned-example/v2": "v2.0.1" 6 | "k8s.io/api": "v0.24.1" 7 | "std.x.io": "v0.3.0" 8 | } 9 | 10 | require: { 11 | "k8s.io/apimachinery": "v0.24.1" @indirect() 12 | } 13 | 14 | replace: { 15 | "k8s.io/api": "" @import("go") 16 | "k8s.io/apimachinery": "" @import("go") 17 | } 18 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/a/cue.mod/module.sum: -------------------------------------------------------------------------------- 1 | github.com/octohelm/cuemod-versioned-example v0.0.0-20230822070100-38465a937b3c h1:j0f2vNEf469zpLPikhs2Vd/F+4COQs2pDbEKVgFFv0k= 2 | github.com/octohelm/cuemod-versioned-example/v2 v2.0.1 h1:mZN1uH9VBQvXplE0/yUxtpgMCEmZxz2PHsgidC4aFQk= 3 | github.com/octohelm/cuemod-versioned-example/v2 v2.0.1 h1:mZN1uH9VBQvXplE0/yUxtpgMCEmZxz2PHsgidC4aFQk= 4 | k8s.io/api v0.24.1 h1:BjCMRDcyEYz03joa3K1+rbshwh1Ay6oB53+iUx2H8UY= 5 | k8s.io/apimachinery v0.24.1 h1:ShD4aDxTQKN5zNf8K1RQ2u98ELLdIW7jEnlO9uAMX/I= 6 | std.x.io v0.3.0 h1:zMsusLxlZQl+XnDx7sJb/FTmknIKYsZ767TnFxIPQow= 7 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/a/defs.cue: -------------------------------------------------------------------------------- 1 | package a 2 | 3 | import ( 4 | "k8s.io/api/core/v1" 5 | 6 | v0 "github.com/octohelm/cuemod-versioned-example/cuepkg" 7 | v2 "github.com/octohelm/cuemod-versioned-example/v2/cuepkg" 8 | 9 | root "github.com/octohelm/cuemod-versioned-example:example" 10 | ) 11 | 12 | services: [Name=_]: v1.#Service & { 13 | metadata: name: Name 14 | metadata: labels: app: Name 15 | metadata: labels: version: "\(v0.#Version) \(v2.#Version) \(root.#Version)" 16 | } 17 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/a/main.cue: -------------------------------------------------------------------------------- 1 | package a 2 | 3 | import ( 4 | j "encoding/json" 5 | 6 | stda "std.x.io/a" 7 | ) 8 | 9 | services: test: { 10 | _hidden: true 11 | 12 | metadata: annotations: configAsJson: j.Marshal({a: int: 1}) 13 | metadata: annotations: { 14 | configAsToml: j.Marshal({a: int: 1, version: stda.#Version}) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/b/cue.mod/.gitignore: -------------------------------------------------------------------------------- 1 | gen/ 2 | pkg/ 3 | module.sum -------------------------------------------------------------------------------- /pkg/cuemod/testdata/b/cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "github.com/x/b" 2 | 3 | require: { 4 | "github.com/x/a": "v0.0.0" 5 | } 6 | 7 | require: { 8 | "github.com/octohelm/cuemod-versioned-example": "v0.0.0-20230822070100-38465a937b3c" @indirect() 9 | "github.com/octohelm/cuemod-versioned-example/v2": "v2.0.1" @indirect() 10 | "k8s.io/api": "v0.24.1" @indirect() 11 | "k8s.io/apimachinery": "v0.24.1" @indirect() 12 | "std.x.io": "v0.3.0" @indirect() 13 | } 14 | 15 | replace: { 16 | // local replace 17 | "github.com/x/a": "../a" 18 | } 19 | 20 | replace: { 21 | "k8s.io/api": "" @import("go") 22 | "k8s.io/apimachinery": "" @import("go") 23 | } 24 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/b/cue.mod/module.sum: -------------------------------------------------------------------------------- 1 | github.com/octohelm/cuemod-versioned-example v0.0.0-20230822070100-38465a937b3c h1:j0f2vNEf469zpLPikhs2Vd/F+4COQs2pDbEKVgFFv0k= 2 | github.com/octohelm/cuemod-versioned-example/v2 v2.0.1 h1:mZN1uH9VBQvXplE0/yUxtpgMCEmZxz2PHsgidC4aFQk= 3 | github.com/octohelm/cuemod-versioned-example/v2 v2.0.1 h1:mZN1uH9VBQvXplE0/yUxtpgMCEmZxz2PHsgidC4aFQk= 4 | github.com/x/a v0.0.0 5 | k8s.io/api v0.24.1 h1:BjCMRDcyEYz03joa3K1+rbshwh1Ay6oB53+iUx2H8UY= 6 | k8s.io/apimachinery v0.24.1 h1:ShD4aDxTQKN5zNf8K1RQ2u98ELLdIW7jEnlO9uAMX/I= 7 | std.x.io v0.3.0 h1:zMsusLxlZQl+XnDx7sJb/FTmknIKYsZ767TnFxIPQow= 8 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/b/cue.mod/usr/github.com/x/b: -------------------------------------------------------------------------------- 1 | /Users/morlay/src/github.com/octohelm/cuemod/pkg/cuemod/testdata/b -------------------------------------------------------------------------------- /pkg/cuemod/testdata/b/cuepkg/c/c.cue: -------------------------------------------------------------------------------- 1 | package c 2 | 3 | import ( 4 | "github.com/x/a" 5 | ) 6 | 7 | services: a.services 8 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/b/cuepkg/c/cue.mod/.gitignore: -------------------------------------------------------------------------------- 1 | gen/ 2 | pkg/ -------------------------------------------------------------------------------- /pkg/cuemod/testdata/b/cuepkg/c/cue.mod/module.cue: -------------------------------------------------------------------------------- 1 | module: "github.com/x/b" 2 | 3 | require: { 4 | "github.com/x/a": "v0.0.0" 5 | } 6 | 7 | require: { 8 | "k8s.io/api": "v0.24.0" @indirect() 9 | "k8s.io/apimachinery": "v0.24.0" @indirect() 10 | } 11 | 12 | replace: { 13 | // local replace 14 | "github.com/x/a": "../a" 15 | } 16 | 17 | replace: { 18 | "k8s.io/api": "" @import("go") 19 | "k8s.io/apimachinery": "" @import("go") 20 | } 21 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/b/cuepkg/c/cue.mod/module.sum: -------------------------------------------------------------------------------- 1 | github.com/x/a v0.0.0 2 | k8s.io/api v0.24.0 h1:J0hann2hfxWr1hinZIDefw7Q96wmCBx6SSB8IY0MdDg= 3 | k8s.io/api/core/v1 v0.24.0 h1:J0hann2hfxWr1hinZIDefw7Q96wmCBx6SSB8IY0MdDg= 4 | k8s.io/apimachinery v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= 5 | k8s.io/apimachinery/pkg/api/resource v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= 6 | k8s.io/apimachinery/pkg/apis/meta/v1 v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= 7 | k8s.io/apimachinery/pkg/runtime v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= 8 | k8s.io/apimachinery/pkg/types v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= 9 | k8s.io/apimachinery/pkg/util/intstr v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= 10 | k8s.io/apimachinery/pkg/watch v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= 11 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/b/main.cue: -------------------------------------------------------------------------------- 1 | package b 2 | 3 | import ( 4 | "github.com/x/b/cuepkg/c" 5 | ) 6 | 7 | sub: c.services 8 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/embedstdlib/pkg.go: -------------------------------------------------------------------------------- 1 | package embedstdlib 2 | 3 | import ( 4 | "embed" 5 | 6 | "github.com/octohelm/cuemod/pkg/cuemod/stdlib" 7 | ) 8 | 9 | var ( 10 | //go:embed std.x.io 11 | FS embed.FS 12 | ) 13 | 14 | func init() { 15 | stdlib.Register(FS, "v0.3.0", "std.x.io") 16 | } 17 | -------------------------------------------------------------------------------- /pkg/cuemod/testdata/embedstdlib/std.x.io/a/hello.cue: -------------------------------------------------------------------------------- 1 | package a 2 | 3 | #Version: "-" 4 | -------------------------------------------------------------------------------- /pkg/cuemod/util.go: -------------------------------------------------------------------------------- 1 | package cuemod 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "strings" 8 | 9 | "golang.org/x/mod/semver" 10 | ) 11 | 12 | func versionGreaterThan(v string, w string) bool { 13 | if w == "" { 14 | return false 15 | } 16 | return semver.Compare(v, w) > 0 17 | } 18 | 19 | func isSubDirFor(targetpath string, root string) bool { 20 | targetpath = targetpath + "/" 21 | root = root + "/" 22 | return strings.HasPrefix(targetpath, root) 23 | } 24 | 25 | func subDir(pkg string, importPath string) (string, error) { 26 | if isSubDirFor(importPath, pkg) { 27 | if len(importPath) > len(pkg)+1 { 28 | return importPath[len(pkg)+1:], nil 29 | } 30 | return "", nil 31 | } 32 | return "", fmt.Errorf("%s is not sub CompletePath of %s", importPath, pkg) 33 | } 34 | 35 | func replaceImportPath(to string, from string, importPath string) string { 36 | if from == importPath { 37 | return to 38 | } 39 | s, _ := subDir(from, importPath) 40 | return filepath.Join(to, s) 41 | } 42 | 43 | func paths(path string) []string { 44 | paths := make([]string, 0) 45 | d := path 46 | for { 47 | paths = append(paths, d) 48 | if !strings.Contains(d, "/") { 49 | break 50 | } 51 | d = filepath.Join(d, "../") 52 | } 53 | return paths 54 | } 55 | 56 | func writeFile(filename string, data []byte) error { 57 | if err := os.MkdirAll(filepath.Dir(filename), os.ModePerm); err != nil { 58 | return err 59 | } 60 | return os.WriteFile(filename, data, os.ModePerm) 61 | } 62 | -------------------------------------------------------------------------------- /pkg/cuemodx/eval.go: -------------------------------------------------------------------------------- 1 | package cuemodx 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | 8 | "cuelang.org/go/cue/load" 9 | cueparser "cuelang.org/go/cue/parser" 10 | "github.com/octohelm/cuemod/pkg/cuemod" 11 | "github.com/octohelm/cuemod/pkg/cuex" 12 | ) 13 | 14 | func EvalContextWithPatches(ctx context.Context, r *cuemod.Context, inputs []string, options ...cuex.EvalOptionFunc) ([]byte, error) { 15 | files := make([]string, 0) 16 | inputSources := map[string]load.Source{} 17 | 18 | c := 0 19 | for i := range inputs { 20 | input := inputs[i] 21 | if input == "" { 22 | continue 23 | } 24 | 25 | var s load.Source 26 | if input[0] == '{' { 27 | s = load.FromString(input) 28 | input = fmt.Sprintf("./input_____%d.cue", i) 29 | } else { 30 | info, err := os.Stat(input) 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | if info.IsDir() { 36 | s = load.FromString(fmt.Sprintf(` 37 | import t "%s" 38 | t 39 | `, r.CompletePath(input))) 40 | input = fmt.Sprintf("./input_%d.cue", i) 41 | } else { 42 | src, err := os.ReadFile(input) 43 | if err != nil { 44 | return nil, err 45 | } 46 | f, err := cueparser.ParseFile(input, src) 47 | if err != nil { 48 | return nil, err 49 | } 50 | s = load.FromFile(f) 51 | } 52 | } 53 | 54 | input = r.CompletePath(input) 55 | 56 | files = append(files, input) 57 | inputSources[input] = s 58 | 59 | c++ 60 | } 61 | 62 | inst := r.Build(ctx, files, cuemod.OptOverlay(inputSources)) 63 | 64 | results, err := cuex.Eval(inst, options...) 65 | if err != nil { 66 | return nil, err 67 | } 68 | return results, nil 69 | } 70 | 71 | func EvalContext(ctx context.Context, r *cuemod.Context, filename string, options ...cuex.EvalOptionFunc) ([]byte, error) { 72 | filename = r.CompletePath(filename) 73 | inst := r.Build(ctx, []string{filename}) 74 | results, err := cuex.Eval(inst, options...) 75 | if err != nil { 76 | return nil, err 77 | } 78 | return results, nil 79 | } 80 | -------------------------------------------------------------------------------- /pkg/cuex/build.go: -------------------------------------------------------------------------------- 1 | package cuex 2 | 3 | import ( 4 | "cuelang.org/go/cue/build" 5 | cueparser "cuelang.org/go/cue/parser" 6 | ) 7 | 8 | func InstanceFromRaw(src []byte) (*build.Instance, error) { 9 | inst := build.NewContext().NewInstance("", nil) 10 | f, err := cueparser.ParseFile("main.cue", src) 11 | if err != nil { 12 | return nil, err 13 | } 14 | if err := inst.AddSyntax(f); err != nil { 15 | return nil, err 16 | } 17 | return inst, nil 18 | } 19 | 20 | func InstanceFromTemplateAndOverwrites(template []byte, overwrites []byte) (*build.Instance, error) { 21 | t, err := InstanceFromRaw(template) 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | if overwrites == nil { 27 | overwrites = []byte(` 28 | import t "t" 29 | t & {} 30 | `) 31 | } 32 | 33 | m, err := InstanceFromRaw(overwrites) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | t.ImportPath = "t" 39 | 40 | m.Imports = append(m.Imports, t) 41 | 42 | return m, nil 43 | } 44 | -------------------------------------------------------------------------------- /pkg/cuex/build_test.go: -------------------------------------------------------------------------------- 1 | package cuex 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestInstanceFromRaw(t *testing.T) { 9 | inst, _ := InstanceFromTemplateAndOverwrites([]byte(` 10 | name: test: *"1111" | string 11 | `), []byte(` 12 | import t "t" 13 | 14 | t & { 15 | name: test: "2222" 16 | } 17 | `)) 18 | data, err := Eval(inst, WithEncoding(CUE)) 19 | fmt.Println(string(data), err) 20 | 21 | data2, err2 := Eval(inst, WithEncoding(YAML)) 22 | fmt.Println(string(data2), err2) 23 | } 24 | -------------------------------------------------------------------------------- /pkg/cuex/eval.go: -------------------------------------------------------------------------------- 1 | package cuex 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | 9 | "cuelang.org/go/cue" 10 | "cuelang.org/go/cue/build" 11 | "cuelang.org/go/cue/cuecontext" 12 | cueerrors "cuelang.org/go/cue/errors" 13 | "sigs.k8s.io/yaml" 14 | ) 15 | 16 | type Encoding = build.Encoding 17 | 18 | const ( 19 | JSON = build.JSON 20 | YAML = build.YAML 21 | CUE = build.CUE 22 | ) 23 | 24 | type EvalOptionFunc = func(o *EvalOption) 25 | 26 | type EvalOption struct { 27 | Encoding Encoding 28 | } 29 | 30 | func (o *EvalOption) SetDefaults() { 31 | if o.Encoding == "" { 32 | o.Encoding = build.JSON 33 | } 34 | } 35 | 36 | func WithEncoding(e build.Encoding) EvalOptionFunc { 37 | return func(o *EvalOption) { 38 | o.Encoding = e 39 | } 40 | } 41 | 42 | func WithEncodingFromFileExt(ext string) EvalOptionFunc { 43 | return func(o *EvalOption) { 44 | switch v := ext; v { 45 | case ".yaml": 46 | o.Encoding = YAML 47 | case ".json": 48 | o.Encoding = JSON 49 | case ".cue": 50 | o.Encoding = CUE 51 | default: 52 | panic(fmt.Errorf("unsupport output format %s", v)) 53 | } 54 | } 55 | } 56 | 57 | func Eval(instance *build.Instance, options ...EvalOptionFunc) ([]byte, error) { 58 | o := &EvalOption{} 59 | 60 | for i := range options { 61 | options[i](o) 62 | } 63 | 64 | v := cuecontext.New().BuildInstance(instance) 65 | 66 | if err := v.Validate(cue.Final(), cue.Concrete(true)); err != nil { 67 | b := bytes.NewBuffer(nil) 68 | cueerrors.Print(b, err, nil) 69 | return nil, errors.New(b.String()) 70 | } 71 | 72 | data, err := encode(instance, v, o.Encoding) 73 | if err != nil { 74 | return nil, err 75 | } 76 | 77 | return data, nil 78 | } 79 | 80 | func encode(inst *build.Instance, v cue.Value, encoding Encoding) ([]byte, error) { 81 | switch encoding { 82 | case CUE: 83 | return BundleToRaw(inst) 84 | case JSON: 85 | return json.Marshal(v) 86 | case YAML: 87 | data, err := json.Marshal(v) 88 | if err != nil { 89 | return nil, err 90 | } 91 | return yaml.JSONToYAML(data) 92 | } 93 | return nil, fmt.Errorf("unsupoort encoding %s", encoding) 94 | } 95 | -------------------------------------------------------------------------------- /pkg/cuex/format/format.go: -------------------------------------------------------------------------------- 1 | package format 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "fmt" 7 | "io" 8 | "os" 9 | "path/filepath" 10 | 11 | "cuelang.org/go/cue/format" 12 | "github.com/go-courier/logr" 13 | ) 14 | 15 | // FormatOpts 16 | type FormatOpts struct { 17 | // ReplaceFile when enabled, will write formatted code to same file 18 | ReplaceFile bool `flag:"write,w" desc:"write result to (source) file instead of stdout"` 19 | // PrintNames when enabled, will print formatted result of each file 20 | PrintNames bool `flag:"list,l" ` 21 | } 22 | 23 | // FormatFiles format jsonnet files 24 | func FormatFiles(ctx context.Context, files []string, opt FormatOpts) error { 25 | log := logr.FromContext(ctx) 26 | 27 | writeFile := func(file string, data []byte) error { 28 | f, _ := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0) 29 | defer f.Close() 30 | _, err := io.Copy(f, bytes.NewBuffer(data)) 31 | return err 32 | } 33 | 34 | cwd, _ := os.Getwd() 35 | 36 | for i := range files { 37 | file := files[i] 38 | 39 | data, err := os.ReadFile(file) 40 | if err != nil { 41 | return err 42 | } 43 | 44 | file, _ = filepath.Rel(cwd, file) 45 | 46 | formatted, changed, err := Format(data) 47 | if err != nil { 48 | return err 49 | } 50 | 51 | if changed { 52 | if opt.PrintNames { 53 | log.Info(fmt.Sprintf("`%s` formatted.", file)) 54 | } 55 | 56 | if opt.ReplaceFile { 57 | if err := writeFile(file, formatted); err != nil { 58 | return err 59 | } 60 | } else { 61 | fmt.Printf(` 62 | // %s 63 | 64 | %s 65 | `, file, formatted) 66 | } 67 | } else { 68 | if opt.PrintNames { 69 | log.Info(fmt.Sprintf("`%s` no changes.", file)) 70 | } 71 | } 72 | } 73 | 74 | return nil 75 | } 76 | 77 | func Format(src []byte) ([]byte, bool, error) { 78 | formatted, err := format.Source(src, format.Simplify()) 79 | if err != nil { 80 | return nil, false, err 81 | } 82 | return formatted, !bytes.Equal(formatted, src), nil 83 | } 84 | -------------------------------------------------------------------------------- /pkg/modutil/revinfo.go: -------------------------------------------------------------------------------- 1 | package modutil 2 | 3 | import ( 4 | "context" 5 | "path" 6 | "strings" 7 | _ "unsafe" 8 | 9 | "github.com/pkg/errors" 10 | 11 | "golang.org/x/mod/modfile" 12 | "golang.org/x/mod/module" 13 | 14 | "github.com/octohelm/cuemod/internal/cmd/go/internals/modfetch" 15 | "github.com/octohelm/cuemod/internal/cmd/go/internals/modfetch/codehost" 16 | "github.com/octohelm/cuemod/internal/cmd/go/internals/vcs" 17 | "github.com/octohelm/cuemod/pkg/version" 18 | ) 19 | 20 | //go:linkname newCodeRepo github.com/octohelm/cuemod/internal/cmd/go/internals/modfetch.newCodeRepo 21 | func newCodeRepo(code codehost.Repo, codeRoot, path string) (modfetch.Repo, error) 22 | 23 | //go:linkname lookupCodeRepo github.com/octohelm/cuemod/internal/cmd/go/internals/modfetch.lookupCodeRepo 24 | func lookupCodeRepo(ctx context.Context, rr *vcs.RepoRoot) (codehost.Repo, error) 25 | 26 | func finalLookupCodeRepo(ctx context.Context, rr *vcs.RepoRoot, localOk bool) (codehost.Repo, error) { 27 | if strings.ToLower(rr.VCS.Name) == "git" && localOk { 28 | return codehost.LocalGitRepo(ctx, path.Join(rr.Root, ".git")) 29 | } 30 | return lookupCodeRepo(ctx, rr) 31 | } 32 | 33 | type RevInfo = modfetch.RevInfo 34 | 35 | func RevInfoFromDir(ctx context.Context, dir string) (*RevInfo, error) { 36 | rootDir, c, err := vcs.FromDir(dir, "", true) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | repo, err := c.RemoteRepo(c, rootDir) 42 | if err != nil { 43 | return nil, errors.Wrap(err, "resolve remote repo failed") 44 | } 45 | 46 | head, err := c.Status(c, rootDir) 47 | if err != nil { 48 | return nil, errors.Wrapf(err, "stat faield") 49 | } 50 | 51 | rr := &vcs.RepoRoot{} 52 | rr.VCS = c 53 | rr.Root = rootDir 54 | rr.Repo = repo 55 | 56 | code, err := finalLookupCodeRepo(ctx, rr, true) 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | importPath := rr.Root 62 | 63 | data, err := code.ReadFile(ctx, head.Revision, "go.mod", -1) 64 | if err == nil { 65 | f, err := modfile.ParseLax("go.mod", data, nil) 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | // /v2 71 | _, pathMajor, ok := module.SplitPathVersion(f.Module.Mod.Path) 72 | if ok && pathMajor != "" { 73 | importPath += pathMajor 74 | } 75 | } 76 | 77 | r, err := newCodeRepo(code, rr.Root, importPath) 78 | if err != nil { 79 | return nil, err 80 | } 81 | 82 | info, err := r.Stat(ctx, head.Revision) 83 | if err != nil { 84 | return nil, errors.Wrapf(err, "stat faield") 85 | } 86 | 87 | info.Version = version.Convert(info.Version, info.Time, info.Short, head.Uncommitted) 88 | 89 | return info, nil 90 | } 91 | -------------------------------------------------------------------------------- /pkg/modutil/revinfo.s: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/octohelm/cuemod/66d8c72c4691efa978dfa6e5452f0497bb2b7060/pkg/modutil/revinfo.s -------------------------------------------------------------------------------- /pkg/modutil/revinfo_test.go: -------------------------------------------------------------------------------- 1 | package modutil 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "testing" 8 | 9 | "golang.org/x/mod/module" 10 | ) 11 | 12 | func TestRevInfoFromDir(t *testing.T) { 13 | cwd, _ := os.Getwd() 14 | info, err := RevInfoFromDir(context.Background(), cwd) 15 | if err != nil { 16 | t.Fatal(err) 17 | } 18 | fmt.Println(info.Version) 19 | fmt.Println(module.PseudoVersionBase(info.Version)) 20 | } 21 | -------------------------------------------------------------------------------- /pkg/modutil/util.go: -------------------------------------------------------------------------------- 1 | package modutil 2 | 3 | import ( 4 | "context" 5 | "strings" 6 | 7 | "golang.org/x/mod/module" 8 | 9 | "github.com/octohelm/cuemod/internal/cmd/go/internals/cfg" 10 | "github.com/octohelm/cuemod/internal/cmd/go/internals/modfetch" 11 | "github.com/octohelm/cuemod/internal/cmd/go/internals/modload" 12 | "github.com/octohelm/cuemod/internal/cmd/go/internals/vcs" 13 | "github.com/octohelm/cuemod/internal/cmd/go/internals/web" 14 | ) 15 | 16 | type Module struct { 17 | Path string 18 | Version string 19 | Error string 20 | Dir string 21 | Sum string 22 | } 23 | 24 | func envOr(key, def string) string { 25 | val := cfg.Getenv(key) 26 | if val == "" { 27 | val = def 28 | } 29 | return val 30 | } 31 | 32 | func init() { 33 | cfg.GOPROXY = envOr("GOPROXY", "https://proxy.golang.org,direct") 34 | cfg.GOSUMDB = envOr("GOSUMDB", "sum.golang.org") 35 | } 36 | 37 | func RepoRootForImportPath(importPath string) (string, error) { 38 | r, err := vcs.RepoRootForImportPath(importPath, vcs.IgnoreMod, web.DefaultSecurity) 39 | if err != nil { 40 | return "", err 41 | } 42 | return r.Root, nil 43 | } 44 | 45 | // Get Module 46 | func Get(ctx context.Context, path string, version string, verbose bool) *Module { 47 | mv := module.Version{Path: path, Version: version} 48 | p, err := modfetch.DownloadDir(ctx, mv) 49 | if err == nil { 50 | // found in cache 51 | return &Module{ 52 | Path: mv.Path, 53 | Version: mv.Version, 54 | Dir: p, 55 | Sum: modfetch.Sum(ctx, mv), 56 | } 57 | } 58 | 59 | modload.ForceUseModules = true 60 | cfg.BuildX = verbose 61 | 62 | requestPath := path + "@" + version 63 | if strings.HasSuffix(path, ".v3") { 64 | requestPath = path 65 | } 66 | 67 | found, err := modload.ListModules(ctx, []string{requestPath}, modload.ListVersions, "") 68 | if err != nil { 69 | panic(err) 70 | } 71 | if len(found) > 0 { 72 | info := found[0] 73 | 74 | m := &Module{ 75 | Path: info.Path, 76 | Version: info.Version, 77 | } 78 | 79 | if info.Error != nil { 80 | m.Error = info.Error.Err 81 | } else { 82 | m.Dir = info.Dir 83 | m.Sum = modfetch.Sum(ctx, module.Version{Path: m.Path, Version: m.Version}) 84 | } 85 | return m 86 | } 87 | return nil 88 | } 89 | 90 | // Download Module 91 | func Download(ctx context.Context, m *Module) { 92 | mv := module.Version{Path: m.Path, Version: m.Version} 93 | dir, err := modfetch.DownloadDir(ctx, mv) 94 | if err == nil { 95 | // found in cache 96 | m.Dir = dir 97 | m.Sum = modfetch.Sum(ctx, module.Version{Path: m.Path, Version: m.Version}) 98 | return 99 | } 100 | 101 | dir, err = modfetch.Download(ctx, mv) 102 | if err != nil { 103 | m.Error = err.Error() 104 | return 105 | } 106 | m.Dir = dir 107 | m.Sum = modfetch.Sum(ctx, module.Version{Path: m.Path, Version: m.Version}) 108 | } 109 | -------------------------------------------------------------------------------- /pkg/modutil/util_test.go: -------------------------------------------------------------------------------- 1 | package modutil 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | func TestDownload(t *testing.T) { 11 | ctx := context.Background() 12 | 13 | pkgs := map[string]string{ 14 | "k8s.io/api": "v0.24.0", 15 | "github.com/rancher/local-path-provisioner": "v0.0.19", 16 | "github.com/grafana/jsonnet-libs": "master", 17 | } 18 | 19 | for p, v := range pkgs { 20 | t.Run("download "+p+"@"+v, func(t *testing.T) { 21 | e := Get(ctx, p, v, true) 22 | t.Log(e.Path, e.Version, e.Dir, e.Sum) 23 | NewWithT(t).Expect(e.Error).To(BeEmpty()) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /pkg/version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "golang.org/x/mod/module" 8 | "golang.org/x/mod/semver" 9 | ) 10 | 11 | func Convert(version string, t time.Time, rev string, dirty bool) string { 12 | exact := true 13 | base, err := module.PseudoVersionBase(version) 14 | if err == nil { 15 | version = base 16 | exact = false 17 | } 18 | if version == "" { 19 | version = "v0.0.0" 20 | exact = true 21 | } 22 | if dirty { 23 | version += "-dirty" 24 | exact = false 25 | } 26 | return pseudoVersion(version, t, rev, exact) 27 | } 28 | 29 | func pseudoVersion(version string, t time.Time, rev string, exact bool) string { 30 | major := semver.Major(version) 31 | if major == "" { 32 | major = "v0" 33 | } 34 | 35 | if exact { 36 | build := semver.Build(version) 37 | segment := fmt.Sprintf("%s-%s", t.UTC().Format(module.PseudoVersionTimestampFormat), rev) 38 | version = semver.Canonical(version) 39 | if version == "" { 40 | version = major + ".0.0" 41 | } 42 | return version + "-" + segment + build 43 | } 44 | 45 | return module.PseudoVersion( 46 | major, 47 | version, 48 | t, 49 | rev, 50 | ) 51 | } 52 | -------------------------------------------------------------------------------- /pkg/version/version_test.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | . "github.com/octohelm/x/testing" 8 | "golang.org/x/mod/module" 9 | ) 10 | 11 | func TestConvert(t *testing.T) { 12 | mustTime := func(s string) time.Time { 13 | t, _ := time.Parse(module.PseudoVersionTimestampFormat, s) 14 | return t 15 | } 16 | 17 | t.Run("when v0.0.0", func(t *testing.T) { 18 | v := Convert( 19 | "v0.0.0-20230809023744-57fc047576ed", 20 | mustTime("20230809023744"), 21 | "57fc047576ed", 22 | false, 23 | ) 24 | 25 | Expect(t, v, Equal("v0.0.0-20230809023744-57fc047576ed")) 26 | 27 | t.Run("when dirty", func(t *testing.T) { 28 | v := Convert( 29 | "v0.0.0-20230809023744-57fc047576ed", 30 | mustTime("20230809023744"), 31 | "57fc047576ed", 32 | true, 33 | ) 34 | 35 | Expect(t, v, Equal("v0.0.0-dirty.0.20230809023744-57fc047576ed")) 36 | }) 37 | }) 38 | 39 | t.Run("when vX.Y.Z", func(t *testing.T) { 40 | v := Convert( 41 | "v1.1.0", 42 | mustTime("20230809023744"), 43 | "57fc047576ed", 44 | false, 45 | ) 46 | 47 | Expect(t, v, Equal("v1.1.0-20230809023744-57fc047576ed")) 48 | 49 | t.Run("when dirty", func(t *testing.T) { 50 | v := Convert( 51 | "v1.1.0", 52 | mustTime("20230809023744"), 53 | "57fc047576ed", 54 | true, 55 | ) 56 | 57 | Expect(t, v, Equal("v1.1.0-dirty.0.20230809023744-57fc047576ed")) 58 | }) 59 | }) 60 | 61 | t.Run("when vX.Y.(Z+1)-0", func(t *testing.T) { 62 | v := Convert( 63 | "v1.1.1-0.20230809023744-57fc047576ed", 64 | mustTime("20230809023744"), 65 | "57fc047576ed", 66 | false, 67 | ) 68 | 69 | Expect(t, v, Equal("v1.1.1-0.20230809023744-57fc047576ed")) 70 | 71 | t.Run("when dirty", func(t *testing.T) { 72 | v := Convert( 73 | "v1.1.1-0.20230809023744-57fc047576ed", 74 | mustTime("20230809023744"), 75 | "57fc047576ed", 76 | true, 77 | ) 78 | 79 | Expect(t, v, Equal("v1.1.0-dirty.0.20230809023744-57fc047576ed")) 80 | }) 81 | }) 82 | } 83 | -------------------------------------------------------------------------------- /wagon.cue: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "strings" 5 | 6 | "wagon.octohelm.tech/core" 7 | "github.com/innoai-tech/runtime/cuepkg/golang" 8 | ) 9 | 10 | client: core.#Client & { 11 | env: { 12 | GH_USERNAME: string | *"" 13 | GH_PASSWORD: core.#Secret 14 | } 15 | } 16 | 17 | pkg: version: core.#Version & {} 18 | 19 | settings: core.#Setting & { 20 | registry: "ghcr.io": auth: { 21 | username: client.env.GH_USERNAME 22 | secret: client.env.GH_PASSWORD 23 | } 24 | } 25 | 26 | actions: go: golang.#Project & { 27 | source: { 28 | path: "." 29 | include: [ 30 | "cmd/", 31 | "pkg/", 32 | "internal/", 33 | "go.mod", 34 | "go.sum", 35 | ] 36 | } 37 | 38 | version: "\(pkg.version.output)" 39 | 40 | goos: ["linux", "darwin"] 41 | goarch: ["amd64", "arm64"] 42 | main: "./cmd/cuem" 43 | ldflags: [ 44 | "-s -w", 45 | "-X \(go.module)/internal/version.version=\(go.version)", 46 | ] 47 | 48 | build: pre: [ 49 | "go mod download", 50 | ] 51 | 52 | ship: { 53 | name: "\(strings.Replace(go.module, "github.com/", "ghcr.io/", -1))/\(go.binary)" 54 | from: "gcr.io/distroless/static-debian11:debug" 55 | } 56 | } 57 | --------------------------------------------------------------------------------