├── .envrc ├── .gitignore ├── BUILD.nix ├── README.md ├── cmd ├── .golangci.yml ├── build.go ├── go.mod ├── go.sum ├── inspect.go ├── list.go ├── main.go ├── nix │ ├── build.go │ ├── inspect.go │ ├── instantiate.go │ ├── target.go │ └── target_test.go └── run.go ├── default.nix ├── devshell.toml ├── flake.lock ├── flake.lock.nix ├── flake.nix ├── lib ├── buildTree.nix ├── default.nix └── flattenTree.nix ├── shell.nix └── treefmt.toml /.envrc: -------------------------------------------------------------------------------- 1 | if nix flake info &>/dev/null; then 2 | use flake 3 | else 4 | use nix 5 | fi 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | result 2 | .cache 3 | cmd/bld 4 | -------------------------------------------------------------------------------- /BUILD.nix: -------------------------------------------------------------------------------- 1 | { self 2 | , nixpkgs 3 | , inputs 4 | , ... 5 | }: 6 | with nixpkgs; 7 | let 8 | bld = buildGoModule 9 | { 10 | name = "bld"; 11 | src = nixpkgs.lib.cleanSource ./cmd; 12 | doCheck = true; 13 | checkPhase = '' 14 | HOME=$TMPDIR 15 | ${nixpkgs.golangci-lint}/bin/golangci-lint run 16 | ''; 17 | vendorHash = "sha256-jmBacHgDzFUqO/ZsaMazcN6r37Yy2VXQdQ4p4CUkTUc"; 18 | }; 19 | lib = import ./lib; 20 | devshell = import inputs.devshell { inherit system; inherit nixpkgs; }; 21 | in 22 | { 23 | inherit bld lib; 24 | default = bld; 25 | # legacy attribute... 26 | bin = bld; 27 | devShell = devshell.mkShell { 28 | imports = [ (devshell.importTOML ./devshell.toml) ]; 29 | }; 30 | 31 | # Example for a run target. You can execute this with `bld run hello` 32 | hello = nixpkgs.writeShellScriptBin "hello" '' 33 | ${nixpkgs.lib.getExe nixpkgs.hello} "$@" 34 | ''; 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bld 2 | 3 | **The experiment is over for now. For most use-cases, something like [blueprint](https://github.com/numtide/blueprint) is good enough.** 4 | 5 | bld is an experimental build tool for monorepos inspired by Bazel, and 6 | implemented with Nix. This is meant to evolve and its current form is not the 7 | final one. 8 | 9 | This tool has two sides: a CLI and a Nix library, that are meant to be able to 10 | work together. 11 | 12 | ## Principles 13 | 14 | We steal the notion of "targets" from Bazel, making each folder open-ended. 15 | 16 | It should be possible to type `bld` in any folder and get the build output of 17 | the current folder (and below?). 18 | 19 | It should be possible to build any targets using purely `nix-build`. 20 | 21 | ## Usage 22 | 23 | `$ bld --help` 24 | ``` 25 | Usage: bld 26 | 27 | Flags: 28 | -h, --help Show context-sensitive help. 29 | --debug 30 | 31 | Commands: 32 | build [] 33 | Build target 34 | 35 | list [] 36 | List available targets 37 | 38 | run [] 39 | Run executable target 40 | 41 | inspect [] 42 | Show build information about target 43 | 44 | Run "bld --help" for more information on a command. 45 | ``` 46 | 47 | The following examples are from this repository. 48 | 49 | 50 |
51 | To list all targets. 52 | 53 | `$ bld list` 54 | ```A 55 | bin 56 | default 57 | devShell 58 | hello 59 | ``` 60 |
61 | 62 |
63 | To build a target. 64 | 65 | `$ bld build hello` 66 | ``` 67 | INFO[0000] Building target target=hello 68 | /nix/store/9a74wmrh6l9h012xza53ff58v0rx456d-hello 69 | ``` 70 |
71 | 72 |
73 | To run a target. 74 | 75 | `$ bld run hello` 76 | ``` 77 | /nix/store/9a74wmrh6l9h012xza53ff58v0rx456d-hello 78 | Hello, world! 79 | ``` 80 | 81 | This can be also used to pass flags: 82 | 83 | `$ bld run hello -- --help` 84 | ``` 85 | /nix/store/9a74wmrh6l9h012xza53ff58v0rx456d-hello 86 | Print a friendly, customizable greeting. 87 | 88 | -t, --traditional use traditional greeting 89 | -g, --greeting=TEXT use TEXT as the greeting message 90 | 91 | --help display this help and exit 92 | --version output version information and exit 93 | 94 | Report bugs to: bug-hello@gnu.org 95 | GNU Hello home page: 96 | General help using GNU software: 97 | ``` 98 | 99 |
100 | 101 |
102 | To inspect a target. 103 | 104 | `$ bld inspect hello` 105 | ``` 106 | { 107 | "/nix/store/bn6wpa9yqibcy83d2iabh1s5k49lcpb7-hello.drv": { 108 | "args": [ 109 | "-e", 110 | "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh" 111 | ], 112 | "builder": "/nix/store/1b9p07z77phvv2hf6gm9f28syp39f1ag-bash-5.1-p16/bin/bash", 113 | "env": { 114 | "allowSubstitutes": "", 115 | "buildCommand": "target=$out'/bin/hello'\nmkdir -p \"$(dirname \"$target\")\"\n\nif [ -e \"$textPath\" ]; then\n mv \"$textPath\" \"$target\"\nelse\n echo -n \"$text\" > \"$target\"\nfi\n\neval \"$checkPhase\"\n\n(test -n \"$executable\" && chmod +x \"$target\") || true\n", 116 | "buildInputs": "", 117 | "builder": "/nix/store/1b9p07z77phvv2hf6gm9f28syp39f1ag-bash-5.1-p16/bin/bash", 118 | "checkPhase": "/nix/store/1b9p07z77phvv2hf6gm9f28syp39f1ag-bash-5.1-p16/bin/bash -n -O extglob \"$target\"\n", 119 | "cmakeFlags": "", 120 | "configureFlags": "", 121 | "depsBuildBuild": "", 122 | "depsBuildBuildPropagated": "", 123 | "depsBuildTarget": "", 124 | "depsBuildTargetPropagated": "", 125 | "depsHostHost": "", 126 | "depsHostHostPropagated": "", 127 | "depsTargetTarget": "", 128 | "depsTargetTargetPropagated": "", 129 | "doCheck": "", 130 | "doInstallCheck": "", 131 | "enableParallelBuilding": "1", 132 | "enableParallelChecking": "1", 133 | "executable": "1", 134 | "mesonFlags": "", 135 | "name": "hello", 136 | "nativeBuildInputs": "", 137 | "out": "/nix/store/9a74wmrh6l9h012xza53ff58v0rx456d-hello", 138 | "outputs": "out", 139 | "passAsFile": "buildCommand text", 140 | "patches": "", 141 | "preferLocalBuild": "1", 142 | "propagatedBuildInputs": "", 143 | "propagatedNativeBuildInputs": "", 144 | "stdenv": "/nix/store/p93ivxvrf3c2w02la2c6nppmkgdh08y3-stdenv-linux", 145 | "strictDeps": "", 146 | "system": "x86_64-linux", 147 | "text": "#!/nix/store/1b9p07z77phvv2hf6gm9f28syp39f1ag-bash-5.1-p16/bin/bash\n/nix/store/y4mxrg8c6l09lb2szl69vwl4f6441i5k-hello-2.12.1/bin/hello\n\n" 148 | }, 149 | "inputDrvs": { 150 | "/nix/store/6pj63b323pn53gpw3l5kdh1rly55aj15-bash-5.1-p16.drv": [ 151 | "out" 152 | ], 153 | "/nix/store/g6qkwa2xaq6i40cwl9bpjxi19m7q8121-hello-2.12.1.drv": [ 154 | "out" 155 | ], 156 | "/nix/store/zq638s1j77mxzc52ql21l9ncl3qsjb2h-stdenv-linux.drv": [ 157 | "out" 158 | ] 159 | }, 160 | "inputSrcs": [ 161 | "/nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25b-default-builder.sh" 162 | ], 163 | "outputs": { 164 | "out": { 165 | "path": "/nix/store/9a74wmrh6l9h012xza53ff58v0rx456d-hello" 166 | } 167 | }, 168 | "system": "x86_64-linux" 169 | } 170 | } 171 | ``` 172 |
173 | 174 | 175 | ## Future ideas 176 | 177 | * Resolve the targets purely with Nix. It should be necessary to connect the 178 | BUILD.nix files manually like currently. 179 | * Snapshot nixpkgs. In order to speed-up nixpkgs, we want to be able to 180 | snapshot the build outputs that we are going to use. 181 | * Add nix evaluation caching to speed-up builds. 182 | * Introduce incremental rebuild Nix libraries for various languages. 183 | * Hook in pre-processing tools. It should be possible to update a third-party 184 | package hash automatically. 185 | -------------------------------------------------------------------------------- /cmd/.golangci.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | enable: 3 | - errname 4 | - exhaustive 5 | - gci 6 | - gochecknoglobals 7 | - gochecknoinits 8 | - goconst 9 | - godot 10 | - gofumpt 11 | - goheader 12 | - goimports 13 | - gosec 14 | - importas 15 | - ireturn 16 | - lll 17 | - makezero 18 | - misspell 19 | - nakedret 20 | - nestif 21 | - nilerr 22 | - nilnil 23 | - nlreturn 24 | - noctx 25 | - nolintlint 26 | - prealloc 27 | - predeclared 28 | - revive 29 | - rowserrcheck 30 | - stylecheck 31 | - tagliatelle 32 | - tenv 33 | - testpackage 34 | - unconvert 35 | - unparam 36 | - wastedassign 37 | - whitespace 38 | - wsl 39 | -------------------------------------------------------------------------------- /cmd/build.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/alecthomas/kong" 5 | nix "github.com/numtide/bld/nix" 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | type Build struct { 10 | Target string `arg:"" name:"target" help:"Target to build" type:"target" default:"."` 11 | ShowTrace bool `name:"show-trace" help:"Show trace on error"` 12 | JSONOutput bool `name:"json" help:"Return json formatted output"` 13 | } 14 | 15 | func (b *Build) Run(_ *kong.Context) error { 16 | log.WithFields(log.Fields{ 17 | "target": b.Target, 18 | }).Info("Building target") 19 | 20 | rootDirectory, err := getPrjRoot() 21 | if err != nil { 22 | return err 23 | } 24 | 25 | err = nix.Build(rootDirectory, b.Target, b.ShowTrace, b.JSONOutput) 26 | if err != nil { 27 | return err 28 | } 29 | 30 | return nil 31 | } 32 | -------------------------------------------------------------------------------- /cmd/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/numtide/bld 2 | 3 | go 1.17 4 | 5 | require github.com/alecthomas/kong v0.5.0 6 | 7 | require ( 8 | github.com/sirupsen/logrus v1.9.0 9 | github.com/spf13/afero v1.9.2 10 | github.com/stretchr/testify v1.7.0 11 | ) 12 | 13 | require ( 14 | github.com/davecgh/go-spew v1.1.1 // indirect 15 | github.com/pkg/errors v0.9.1 // indirect 16 | github.com/pmezard/go-difflib v1.0.0 // indirect 17 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect 18 | golang.org/x/text v0.3.4 // indirect 19 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /cmd/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 7 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 8 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 9 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= 10 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= 11 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= 12 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= 13 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= 14 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= 15 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= 16 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 17 | cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= 18 | cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= 19 | cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= 20 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 21 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 22 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 23 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= 24 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= 25 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 26 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 27 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 28 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 29 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 30 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= 31 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 32 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 33 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 34 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= 35 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 36 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 37 | cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= 38 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 39 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 40 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 41 | github.com/alecthomas/kong v0.5.0 h1:u8Kdw+eeml93qtMZ04iei0CFYve/WPcA5IFh+9wSskE= 42 | github.com/alecthomas/kong v0.5.0/go.mod h1:uzxf/HUh0tj43x1AyJROl3JT7SgsZ5m+icOv1csRhc0= 43 | github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142 h1:8Uy0oSf5co/NZXje7U1z8Mpep++QJOldL2hs/sBQf48= 44 | github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= 45 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 46 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 47 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 48 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 49 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 50 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 51 | github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 52 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 53 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 54 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 55 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 56 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 57 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 58 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 59 | github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= 60 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 61 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 62 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 63 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 64 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 65 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 66 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 67 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 68 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 69 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 70 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 71 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 72 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 73 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 74 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 75 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 76 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 77 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 78 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 79 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 80 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 81 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 82 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 83 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 84 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 85 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 86 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 87 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 88 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 89 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 90 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 91 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 92 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 93 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 94 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 95 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 96 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 97 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 98 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 99 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 100 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 101 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 102 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 103 | github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 104 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 105 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 106 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 107 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 108 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 109 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 110 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 111 | github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 112 | github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 113 | github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 114 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 115 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 116 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 117 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 118 | github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= 119 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 120 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 121 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 122 | github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 123 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 124 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 125 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 126 | github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 127 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 128 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 129 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 130 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 131 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 132 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 133 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 134 | github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= 135 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 136 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 137 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 138 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 139 | github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= 140 | github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 141 | github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= 142 | github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= 143 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 144 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 145 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 146 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 147 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 148 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 149 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 150 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 151 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 152 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 153 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 154 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 155 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 156 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 157 | go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= 158 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 159 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 160 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 161 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 162 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 163 | golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 164 | golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 165 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 166 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 167 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 168 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 169 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 170 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 171 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 172 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 173 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 174 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 175 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 176 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 177 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 178 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 179 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 180 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 181 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 182 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 183 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 184 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 185 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 186 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 187 | golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 188 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 189 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 190 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 191 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 192 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 193 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 194 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 195 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 196 | golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 197 | golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 198 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 199 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 200 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 201 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 202 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 203 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 204 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 205 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 206 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 207 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 208 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 209 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 210 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 211 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 212 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 213 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 214 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 215 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 216 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 217 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 218 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 219 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 220 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 221 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 222 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 223 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 224 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 225 | golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 226 | golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 227 | golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 228 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 229 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 230 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 231 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 232 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 233 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 234 | golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 235 | golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 236 | golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 237 | golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 238 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 239 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 240 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 241 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 242 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 243 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 244 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 245 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 246 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 247 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 248 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 249 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 250 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 251 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 252 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 253 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 254 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 255 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 256 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 257 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 258 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 259 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 260 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 261 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 262 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 263 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 264 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 265 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 266 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 267 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 268 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 269 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 270 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 271 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 272 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 273 | golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 274 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 275 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 276 | golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 277 | golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 278 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 279 | golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 280 | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 281 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 282 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= 283 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 284 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 285 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 286 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 287 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 288 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 289 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 290 | golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= 291 | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 292 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 293 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 294 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 295 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 296 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 297 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 298 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 299 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 300 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 301 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 302 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 303 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 304 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 305 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 306 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 307 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 308 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 309 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 310 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 311 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 312 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 313 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 314 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 315 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 316 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 317 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 318 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 319 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 320 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 321 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 322 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 323 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 324 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 325 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 326 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 327 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 328 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 329 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 330 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 331 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 332 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 333 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 334 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 335 | golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= 336 | golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 337 | golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 338 | golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 339 | golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 340 | golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 341 | golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= 342 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 343 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 344 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 345 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 346 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 347 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 348 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 349 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 350 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 351 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 352 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 353 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 354 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 355 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 356 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 357 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 358 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 359 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 360 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 361 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 362 | google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= 363 | google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= 364 | google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= 365 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 366 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 367 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 368 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 369 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 370 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 371 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 372 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 373 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 374 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 375 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 376 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 377 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 378 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 379 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 380 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 381 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 382 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 383 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 384 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 385 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 386 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 387 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 388 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 389 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 390 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 391 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 392 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 393 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 394 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 395 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 396 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 397 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 398 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 399 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 400 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 401 | google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 402 | google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 403 | google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 404 | google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 405 | google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 406 | google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 407 | google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 408 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 409 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 410 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 411 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 412 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 413 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 414 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 415 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 416 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 417 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 418 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 419 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 420 | google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 421 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 422 | google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= 423 | google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 424 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 425 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 426 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 427 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 428 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 429 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 430 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 431 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 432 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 433 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 434 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 435 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 436 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 437 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 438 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 439 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 440 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 441 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 442 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 443 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 444 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 445 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 446 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 447 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 448 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 449 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 450 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 451 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 452 | -------------------------------------------------------------------------------- /cmd/inspect.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/alecthomas/kong" 5 | nix "github.com/numtide/bld/nix" 6 | log "github.com/sirupsen/logrus" 7 | ) 8 | 9 | type Inspect struct { 10 | Target string `arg:"" name:"target" help:"Target to inspect" type:"target" default:"."` 11 | } 12 | 13 | func (b *Inspect) Run(_ *kong.Context) error { 14 | log.WithFields(log.Fields{ 15 | "target": b.Target, 16 | }).Debug("Inspect target") 17 | 18 | rootDirectory, err := getPrjRoot() 19 | if err != nil { 20 | return err 21 | } 22 | 23 | err = nix.Inspect(rootDirectory, b.Target) 24 | if err != nil { 25 | return err 26 | } 27 | 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /cmd/list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/alecthomas/kong" 7 | nix "github.com/numtide/bld/nix" 8 | log "github.com/sirupsen/logrus" 9 | ) 10 | 11 | type List struct { 12 | Target string `arg:"" name:"target" help:"Target to build" type:"target" default:"."` 13 | } 14 | 15 | func (l *List) Run(_ *kong.Context) error { 16 | log.Debug("Listing target in directory") 17 | 18 | rootDirectory, err := getPrjRoot() 19 | if err != nil { 20 | return err 21 | } 22 | 23 | result, err := nix.Instantiate(rootDirectory, l.Target, "_list") 24 | if err != nil { 25 | return err 26 | } 27 | 28 | fmt.Println(result) 29 | 30 | return err 31 | } 32 | -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | "os/exec" 8 | "strings" 9 | 10 | "github.com/alecthomas/kong" 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | //nolint:gochecknoglobals 15 | var cli struct { 16 | Debug bool 17 | Build Build `kong:"cmd,name='build',help='Build target',default='withargs'"` 18 | List List `kong:"cmd,name='list',help='List available targets'"` 19 | Run Run `kong:"cmd,name='run',help='Run executable target'"` 20 | Inspect Inspect `kong:"cmd,name='inspect',help='Show build information about target'"` 21 | } 22 | 23 | func getPrjRoot() (string, error) { 24 | if prjRoot := os.Getenv("PRJ_ROOT"); prjRoot != "" { 25 | return prjRoot, nil 26 | } 27 | 28 | cmdOut, err := exec.Command("git", "rev-parse", "--show-toplevel").Output() 29 | if err != nil { 30 | errorMessage := fmt.Sprintf( 31 | "Error looking project root directory %s", err.Error(), 32 | ) 33 | 34 | return "", errors.New(errorMessage) 35 | } 36 | 37 | return strings.TrimSpace(string(cmdOut)), nil 38 | } 39 | 40 | func die(err error) { 41 | fmt.Fprintln(os.Stderr, err) 42 | os.Exit(1) 43 | } 44 | 45 | func main() { 46 | parser, err := kong.New(&cli) 47 | if err != nil { 48 | die(err) 49 | } 50 | 51 | ctx, err := parser.Parse(os.Args[1:]) 52 | if err != nil { 53 | die(err) 54 | } 55 | 56 | if cli.Debug { 57 | log.SetLevel(log.DebugLevel) 58 | } 59 | 60 | // Call the Run() method of the selected parsed command. 61 | err = ctx.Run() 62 | 63 | ctx.FatalIfErrorf(err) 64 | } 65 | -------------------------------------------------------------------------------- /cmd/nix/build.go: -------------------------------------------------------------------------------- 1 | package nix 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | "os/exec" 8 | "strings" 9 | 10 | log "github.com/sirupsen/logrus" 11 | ) 12 | 13 | func Build(rootDirectory, target string, showTrace bool, jsonOutput bool) (err error) { 14 | if err != nil { 15 | errorMessage := fmt.Sprintf( 16 | "Error looking for root directory %s", err.Error(), 17 | ) 18 | 19 | return errors.New(errorMessage) 20 | } 21 | 22 | currentDirectory, err := os.Getwd() 23 | if err != nil { 24 | log.Println(err) 25 | } 26 | 27 | path, attr, err := TargetToAttr(rootDirectory, currentDirectory, target) 28 | if err != nil { 29 | errorMessage := fmt.Sprintf( 30 | "Error mapping target to directory %s", err.Error(), 31 | ) 32 | 33 | return errors.New(errorMessage) 34 | } 35 | 36 | pathToBuild := strings.Trim(fmt.Sprintf("%s/%s", path, attr), "/") 37 | pathToBuild = strings.Replace(pathToBuild, "/", ".", -1) 38 | 39 | cacheDirectory := fmt.Sprintf("%s/.cache/bld", rootDirectory) 40 | 41 | output := "--print-out-paths" 42 | if jsonOutput { 43 | output = "--json" 44 | } 45 | 46 | args := []string{ 47 | "--extra-experimental-features", "nix-command", 48 | "build", 49 | "--include", fmt.Sprintf("prj_root=%s", rootDirectory), 50 | output, 51 | "-L", "--out-link", fmt.Sprintf("%s/result-%s", cacheDirectory, attr), 52 | "-f", "", 53 | pathToBuild, 54 | } 55 | 56 | if showTrace { 57 | args = append(args, "--show-trace") 58 | } 59 | 60 | log.WithFields(log.Fields{"args": args}).Debug("Running nix build") 61 | 62 | cmd := exec.Command("nix", args...) 63 | 64 | cmd.Stdout = os.Stdout 65 | cmd.Stderr = os.Stderr 66 | 67 | err = cmd.Run() 68 | if err != nil { 69 | errorMessage := fmt.Sprintf( 70 | "Error while running `nix build ..`: %s", err.Error(), 71 | ) 72 | 73 | return errors.New(errorMessage) 74 | } 75 | 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /cmd/nix/inspect.go: -------------------------------------------------------------------------------- 1 | package nix 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | "os/exec" 8 | "strings" 9 | 10 | log "github.com/sirupsen/logrus" 11 | ) 12 | 13 | func Inspect(rootDirectory, target string) (err error) { 14 | if err != nil { 15 | errorMessage := fmt.Sprintf( 16 | "Error looking for root directory %s", err.Error(), 17 | ) 18 | 19 | return errors.New(errorMessage) 20 | } 21 | 22 | currentDirectory, err := os.Getwd() 23 | if err != nil { 24 | return err 25 | } 26 | 27 | path, attr, err := TargetToAttr(rootDirectory, currentDirectory, target) 28 | if err != nil { 29 | errorMessage := fmt.Sprintf( 30 | "Error mapping target to directory %s", err.Error(), 31 | ) 32 | 33 | return errors.New(errorMessage) 34 | } 35 | 36 | pathToBuild := strings.Trim(fmt.Sprintf("%s/%s", path, attr), "/") 37 | pathToBuild = strings.Replace(pathToBuild, "/", ".", -1) 38 | 39 | log.WithFields(log.Fields{"pathToBuild": pathToBuild}).Debug("Running nix show-derivation") 40 | 41 | // Eval 42 | var drvPath string 43 | { 44 | args := []string{"--no-gc-warning", "--json"} 45 | if pathToBuild != "" { 46 | args = append(args, "-A", pathToBuild) 47 | } 48 | 49 | cmd := exec.Command("nix-instantiate", args...) 50 | cmd.Stderr = os.Stderr 51 | 52 | bs, err := cmd.Output() 53 | if err != nil { 54 | return fmt.Errorf("error while inspecting the target: %w", err) 55 | } 56 | 57 | drvPath = strings.TrimSpace(string(bs)) 58 | } 59 | 60 | // Show derivation 61 | cmd := exec.Command("nix", "show-derivation", "--extra-experimental-features", "nix-command", drvPath) 62 | cmd.Stdout = os.Stdout 63 | cmd.Stderr = os.Stderr 64 | 65 | err = cmd.Run() 66 | if err != nil { 67 | return fmt.Errorf("error while inspect target: %w", err) 68 | } 69 | 70 | return nil 71 | } 72 | -------------------------------------------------------------------------------- /cmd/nix/instantiate.go: -------------------------------------------------------------------------------- 1 | package nix 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | "os" 9 | "os/exec" 10 | "path/filepath" 11 | "strings" 12 | 13 | log "github.com/sirupsen/logrus" 14 | ) 15 | 16 | func Instantiate(rootDirectory string, target string, attr string) (result string, err error) { 17 | if err != nil { 18 | errorMessage := fmt.Sprintf( 19 | "Error looking for root directory %s", err.Error(), 20 | ) 21 | 22 | return "", errors.New(errorMessage) 23 | } 24 | 25 | currentDirectory, err := os.Getwd() 26 | if err != nil { 27 | log.Println(err) 28 | } 29 | 30 | path, err := TargetToPath(rootDirectory, currentDirectory, target) 31 | if err != nil { 32 | errorMessage := fmt.Sprintf( 33 | "Error mapping target to directory %s", err.Error(), 34 | ) 35 | 36 | return "", errors.New(errorMessage) 37 | } 38 | 39 | pathToBuild := path 40 | 41 | // required for running targets 42 | if !pathExists(path) && pathExists(filepath.Dir(path)) { 43 | path = strings.Replace(path, rootDirectory, "", -1) 44 | pathToBuild = strings.Trim(path, "/") 45 | pathToBuild = strings.Replace(pathToBuild, "/", ".", -1) 46 | } 47 | 48 | args := []string{ 49 | "--eval", 50 | "--include", fmt.Sprintf("prj_root=%s", rootDirectory), 51 | "--expr", fmt.Sprintf("{ path }: (import {}).%s path", attr), 52 | "--argstr", "path", pathToBuild, 53 | "--json", 54 | //"--strict", // TODO: make it optional ? 55 | } 56 | 57 | log.WithFields(log.Fields{"args": args}).Debug("Running nix-instantiate") 58 | 59 | cmd := exec.Command("nix-instantiate", args...) 60 | 61 | var stdout bytes.Buffer 62 | cmd.Stdout = &stdout 63 | cmd.Stderr = os.Stderr 64 | 65 | err = cmd.Run() 66 | if err != nil { 67 | errorMessage := fmt.Sprintf( 68 | "Error while running `nix-instantiate ..`: %s", err.Error(), 69 | ) 70 | 71 | return "", errors.New(errorMessage) 72 | } 73 | 74 | err = json.Unmarshal(stdout.Bytes(), &result) 75 | if err != nil { 76 | return "", err 77 | } 78 | 79 | return result, nil 80 | } 81 | -------------------------------------------------------------------------------- /cmd/nix/target.go: -------------------------------------------------------------------------------- 1 | package nix 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "path/filepath" 7 | "strings" 8 | 9 | log "github.com/sirupsen/logrus" 10 | afero "github.com/spf13/afero" 11 | ) 12 | 13 | //nolint:gochecknoglobals 14 | var ( 15 | FS afero.Fs = afero.NewOsFs() 16 | AppFS *afero.Afero = &afero.Afero{Fs: FS} 17 | ) 18 | 19 | func TargetToPath(rootDirectory string, currentDirectory string, target string) (path string, err error) { 20 | log.WithFields(log.Fields{"target": target}).Debug("targetToPath") 21 | 22 | if target == "..." { 23 | return rootDirectory, nil 24 | } 25 | 26 | if strings.HasPrefix(target, "/") { 27 | currentDirectory = rootDirectory 28 | } 29 | 30 | path, err = filepath.Abs(filepath.Join(currentDirectory, target)) 31 | if err != nil { 32 | errorMessage := fmt.Sprintf( 33 | "Error looking for current absolute path %s", err.Error(), 34 | ) 35 | 36 | return "", errors.New(errorMessage) 37 | } 38 | 39 | log.WithFields(log.Fields{"target": target, "path": path}).Debug("targetToPath other") 40 | 41 | return path, nil 42 | } 43 | 44 | func pathExists(path string) bool { 45 | _, err := AppFS.Stat(path) 46 | 47 | return err == nil 48 | } 49 | 50 | func TargetToAttr(rootDirectory string, currentDirectory string, target string) (path string, attr string, err error) { 51 | pathAndTarget := strings.Split(target, ":") 52 | switch len(pathAndTarget) { 53 | case 1: 54 | switch target = pathAndTarget[0]; { 55 | case target == "...": 56 | path = target 57 | case pathExists(target): 58 | { 59 | path = target 60 | } 61 | case pathExists(filepath.Dir(target)): 62 | { 63 | path, attr = filepath.Split(target) 64 | } 65 | default: 66 | attr = target 67 | } 68 | case 2: 69 | path = pathAndTarget[0] 70 | attr = pathAndTarget[1] 71 | default: 72 | return "", "", errors.New("unable to parse target") 73 | } 74 | 75 | log.WithFields(log.Fields{"target": target}).Debug("targetToAttr") 76 | 77 | path, err = TargetToPath(rootDirectory, currentDirectory, path) 78 | if err != nil { 79 | return "", "", err 80 | } 81 | 82 | pathRelativeToRoot := strings.Replace(path, rootDirectory, "", -1) 83 | 84 | log.WithFields(log.Fields{"relativePathToRoot": pathRelativeToRoot, "attr": attr}).Debug("targetToAttr") 85 | 86 | return pathRelativeToRoot, attr, nil 87 | } 88 | -------------------------------------------------------------------------------- /cmd/nix/target_test.go: -------------------------------------------------------------------------------- 1 | package nix_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/numtide/bld/nix" 7 | afero "github.com/spf13/afero" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func TestTargetToAttr(t *testing.T) { 12 | FS := afero.NewMemMapFs() 13 | nix.AppFS = &afero.Afero{Fs: FS} 14 | err := nix.AppFS.MkdirAll("folder1/folder2", 0o755) 15 | require.NoError(t, err) 16 | 17 | tests := []struct { 18 | rootDirectory string 19 | currentDirectory string 20 | target string 21 | expectedPath string 22 | expectedAttr string 23 | }{ 24 | { 25 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj", target: "pkg1", 26 | expectedPath: "", expectedAttr: "pkg1", 27 | }, 28 | { 29 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj", target: "folder1", 30 | expectedPath: "/folder1", expectedAttr: "", 31 | }, 32 | { 33 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1", target: "pkg1", 34 | expectedPath: "/folder1", expectedAttr: "pkg1", 35 | }, 36 | { 37 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj", target: "folder1:pkg1", 38 | expectedPath: "/folder1", expectedAttr: "pkg1", 39 | }, 40 | { 41 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1", target: "..:pkg1", 42 | expectedPath: "", expectedAttr: "pkg1", 43 | }, 44 | { 45 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1", target: "..", 46 | expectedPath: "", expectedAttr: "", 47 | }, 48 | { 49 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj", target: "folder1/folder2/attr", 50 | expectedPath: "/folder1/folder2", expectedAttr: "attr", 51 | }, 52 | { 53 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1/folder2", target: "../attr", 54 | expectedPath: "/folder1", expectedAttr: "attr", 55 | }, 56 | } 57 | for _, tt := range tests { 58 | path, attr, err := nix.TargetToAttr(tt.rootDirectory, tt.currentDirectory, tt.target) 59 | require.NoError(t, err) 60 | require.Equal(t, tt.expectedPath, path) 61 | require.Equal(t, tt.expectedAttr, attr) 62 | } 63 | } 64 | 65 | func TestTargetToPathAbsolute(t *testing.T) { 66 | tests := []struct { 67 | rootDirectory string 68 | currentDirectory string 69 | target string 70 | expectedPath string 71 | }{ 72 | { 73 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj", target: "/folder1", 74 | expectedPath: "/tmp/prj/folder1", 75 | }, 76 | { 77 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1", target: "/folder1", 78 | expectedPath: "/tmp/prj/folder1", 79 | }, 80 | { 81 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1", target: "//folder1", 82 | expectedPath: "/tmp/prj/folder1", 83 | }, 84 | { 85 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1", target: "/", 86 | expectedPath: "/tmp/prj", 87 | }, 88 | { 89 | rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1", target: "//", 90 | expectedPath: "/tmp/prj", 91 | }, 92 | } 93 | for _, tt := range tests { 94 | path, err := nix.TargetToPath(tt.rootDirectory, tt.currentDirectory, tt.target) 95 | require.NoError(t, err) 96 | require.Equal(t, tt.expectedPath, path) 97 | } 98 | } 99 | 100 | func TestTargetToPathRelative(t *testing.T) { 101 | tests := []struct { 102 | rootDirectory string 103 | currentDirectory string 104 | target string 105 | expectedPath string 106 | }{ 107 | {rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj", target: "folder1", expectedPath: "/tmp/prj/folder1"}, 108 | {rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1", target: "..", expectedPath: "/tmp/prj"}, 109 | {rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1", target: "", expectedPath: "/tmp/prj/folder1"}, 110 | {rootDirectory: "/tmp/prj", currentDirectory: "/tmp/prj/folder1", target: "...", expectedPath: "/tmp/prj"}, 111 | } 112 | for _, tt := range tests { 113 | path, err := nix.TargetToPath(tt.rootDirectory, tt.currentDirectory, tt.target) 114 | require.NoError(t, err) 115 | require.Equal(t, tt.expectedPath, path) 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /cmd/run.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "os" 7 | "os/exec" 8 | 9 | "github.com/alecthomas/kong" 10 | nix "github.com/numtide/bld/nix" 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | type Run struct { 15 | Target string `arg:"" name:"target" help:"Target to run" type:"target" default:"."` 16 | Args []string `arg:"" help:"Arguments to pass to run target." default:"[]"` 17 | ShowTrace bool `name:"show-trace" help:"Show trace on error"` 18 | } 19 | 20 | func (r *Run) Run(_ *kong.Context) error { 21 | log.Debug("Running target in directory") 22 | 23 | rootDirectory, err := getPrjRoot() 24 | if err != nil { 25 | return err 26 | } 27 | 28 | err = nix.Build(rootDirectory, r.Target, r.ShowTrace, false) 29 | if err != nil { 30 | return err 31 | } 32 | 33 | result, err := nix.Instantiate(rootDirectory, r.Target, "_run") 34 | if err != nil { 35 | return err 36 | } 37 | 38 | log.WithFields(log.Fields{"command": result}).Debug("Running target") 39 | 40 | cmd := exec.Command(result, r.Args...) 41 | cmd.Stdout = os.Stdout 42 | cmd.Stderr = os.Stderr 43 | 44 | err = cmd.Run() 45 | if err != nil { 46 | errorMessage := fmt.Sprintf( 47 | "Error while running `%s ..`: %s", result, err.Error(), 48 | ) 49 | 50 | return errors.New(errorMessage) 51 | } 52 | 53 | return err 54 | } 55 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { system ? builtins.currentSystem 2 | , inputs ? import ./flake.lock.nix { } 3 | , nixpkgs ? import inputs.nixpkgs { 4 | inherit system; 5 | # Makes the config pure as well. See /top-level/impure.nix: 6 | config = { }; 7 | overlays = [ ]; 8 | } 9 | }: 10 | let 11 | bld = import ./lib; 12 | in 13 | bld.buildTree { 14 | path = ./.; 15 | args = { 16 | inherit 17 | inputs 18 | nixpkgs 19 | ; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /devshell.toml: -------------------------------------------------------------------------------- 1 | imports = [ 2 | "language.go" 3 | ] 4 | 5 | [devshell] 6 | name = "bld" 7 | packages = [ 8 | "gofumpt", 9 | "nixpkgs-fmt", 10 | "treefmt", 11 | "golangci-lint", 12 | "gcc" 13 | ] 14 | 15 | [[commands]] 16 | name = "fmt" 17 | help = "format code" 18 | command = "treefmt" 19 | 20 | [[commands]] 21 | name = "lint" 22 | help = "lint code" 23 | command = "cd $PRJ_ROOT/cmd && golangci-lint run" 24 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "devshell": { 4 | "inputs": { 5 | "flake-utils": "flake-utils", 6 | "nixpkgs": "nixpkgs" 7 | }, 8 | "locked": { 9 | "lastModified": 1705332421, 10 | "narHash": "sha256-USpGLPme1IuqG78JNqSaRabilwkCyHmVWY0M9vYyqEA=", 11 | "owner": "numtide", 12 | "repo": "devshell", 13 | "rev": "83cb93d6d063ad290beee669f4badf9914cc16ec", 14 | "type": "github" 15 | }, 16 | "original": { 17 | "owner": "numtide", 18 | "repo": "devshell", 19 | "type": "github" 20 | } 21 | }, 22 | "flake-utils": { 23 | "inputs": { 24 | "systems": "systems" 25 | }, 26 | "locked": { 27 | "lastModified": 1701680307, 28 | "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", 29 | "owner": "numtide", 30 | "repo": "flake-utils", 31 | "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", 32 | "type": "github" 33 | }, 34 | "original": { 35 | "owner": "numtide", 36 | "repo": "flake-utils", 37 | "type": "github" 38 | } 39 | }, 40 | "nixpkgs": { 41 | "locked": { 42 | "lastModified": 1704161960, 43 | "narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=", 44 | "owner": "NixOS", 45 | "repo": "nixpkgs", 46 | "rev": "63143ac2c9186be6d9da6035fa22620018c85932", 47 | "type": "github" 48 | }, 49 | "original": { 50 | "owner": "NixOS", 51 | "ref": "nixpkgs-unstable", 52 | "repo": "nixpkgs", 53 | "type": "github" 54 | } 55 | }, 56 | "nixpkgs_2": { 57 | "locked": { 58 | "lastModified": 1708475490, 59 | "narHash": "sha256-g1v0TsWBQPX97ziznfJdWhgMyMGtoBFs102xSYO4syU=", 60 | "owner": "nixos", 61 | "repo": "nixpkgs", 62 | "rev": "0e74ca98a74bc7270d28838369593635a5db3260", 63 | "type": "github" 64 | }, 65 | "original": { 66 | "owner": "nixos", 67 | "ref": "nixos-unstable", 68 | "repo": "nixpkgs", 69 | "type": "github" 70 | } 71 | }, 72 | "root": { 73 | "inputs": { 74 | "devshell": "devshell", 75 | "nixpkgs": "nixpkgs_2" 76 | } 77 | }, 78 | "systems": { 79 | "locked": { 80 | "lastModified": 1681028828, 81 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 82 | "owner": "nix-systems", 83 | "repo": "default", 84 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 85 | "type": "github" 86 | }, 87 | "original": { 88 | "owner": "nix-systems", 89 | "repo": "default", 90 | "type": "github" 91 | } 92 | } 93 | }, 94 | "root": "root", 95 | "version": 7 96 | } 97 | -------------------------------------------------------------------------------- /flake.lock.nix: -------------------------------------------------------------------------------- 1 | # Adapted from https://github.com/edolstra/flake-compat/blob/master/default.nix 2 | # 3 | # This version only gives back the inputs. In that mode, flake becomes little 4 | # more than a niv replacement. 5 | { src ? ./. }: 6 | let 7 | lockFilePath = src + "/flake.lock"; 8 | 9 | lockFile = builtins.fromJSON (builtins.readFile lockFilePath); 10 | 11 | # Emulate builtins.fetchTree 12 | # 13 | # TODO: only implement polyfill if the builtin doesn't exist? 14 | fetchTree = 15 | info: 16 | if info.type == "github" then 17 | { 18 | outPath = fetchTarball { 19 | url = "https://api.${info.host or "github.com"}/repos/${info.owner}/${info.repo}/tarball/${info.rev}"; 20 | sha256 = info.narHash; 21 | }; 22 | rev = info.rev; 23 | shortRev = builtins.substring 0 7 info.rev; 24 | lastModified = info.lastModified; 25 | narHash = info.narHash; 26 | } 27 | else if info.type == "git" then 28 | { 29 | outPath = 30 | builtins.fetchGit 31 | ({ url = info.url; sha256 = info.narHash; } 32 | // (if info ? rev then { inherit (info) rev; } else { }) 33 | // (if info ? ref then { inherit (info) ref; } else { }) 34 | ); 35 | lastModified = info.lastModified; 36 | narHash = info.narHash; 37 | } // (if info ? rev then { 38 | rev = info.rev; 39 | shortRev = builtins.substring 0 7 info.rev; 40 | } else { }) 41 | else if info.type == "path" then 42 | { 43 | outPath = builtins.path { path = info.path; }; 44 | narHash = info.narHash; 45 | } 46 | else if info.type == "tarball" then 47 | { 48 | outPath = fetchTarball { 49 | url = info.url; 50 | sha256 = info.narHash; 51 | }; 52 | narHash = info.narHash; 53 | } 54 | else if info.type == "gitlab" then 55 | { 56 | inherit (info) rev narHash lastModified; 57 | outPath = fetchTarball { 58 | url = "https://${info.host or "gitlab.com"}/api/v4/projects/${info.owner}%2F${info.repo}/repository/archive.tar.gz?sha=${info.rev}"; 59 | sha256 = info.narHash; 60 | }; 61 | shortRev = builtins.substring 0 7 info.rev; 62 | } 63 | else 64 | # FIXME: add Mercurial, tarball inputs. 65 | throw "flake input has unsupported input type '${info.type}'"; 66 | 67 | allNodes = 68 | builtins.mapAttrs 69 | (key: node: 70 | let 71 | sourceInfo = 72 | if key == lockFile.root 73 | then { } 74 | else fetchTree (node.info or { } // removeAttrs node.locked [ "dir" ]); 75 | 76 | inputs = builtins.mapAttrs 77 | (inputName: inputSpec: allNodes.${resolveInput inputSpec}) 78 | (node.inputs or { }); 79 | 80 | # Resolve a input spec into a node name. An input spec is 81 | # either a node name, or a 'follows' path from the root 82 | # node. 83 | resolveInput = inputSpec: 84 | if builtins.isList inputSpec 85 | then getInputByPath lockFile.root inputSpec 86 | else inputSpec; 87 | 88 | # Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the 89 | # root node, returning the final node. 90 | getInputByPath = nodeName: path: 91 | if path == [ ] 92 | then nodeName 93 | else 94 | getInputByPath 95 | # Since this could be a 'follows' input, call resolveInput. 96 | (resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path}) 97 | (builtins.tail path); 98 | 99 | result = sourceInfo // { inherit inputs; inherit sourceInfo; }; 100 | in 101 | if node.flake or true then 102 | result 103 | else 104 | sourceInfo 105 | ) 106 | lockFile.nodes; 107 | 108 | result = 109 | if lockFile.version >= 5 && lockFile.version <= 7 110 | then allNodes.${lockFile.root}.inputs 111 | else throw "lock file '${lockFilePath}' has unsupported version ${toString lockFile.version}"; 112 | 113 | in 114 | result 115 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "bld is an experimental frontend for monorepos"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; 6 | devshell.url = "github:numtide/devshell"; 7 | }; 8 | 9 | nixConfig.extra-substituters = [ "https://numtide.cachix.org/" ]; 10 | nixConfig.extra-trusted-public-keys = [ "numtide.cachix.org-1:2ps1kLBUWjxIneOy1Ik6cQjb41X0iXVXeHigGmycPPE=" ]; 11 | 12 | outputs = { self, nixpkgs, devshell }: 13 | let 14 | supportedSystems = [ 15 | "aarch64-darwin" 16 | "aarch64-linux" 17 | "x86_64-darwin" 18 | "x86_64-linux" 19 | ]; 20 | forAllSystems = nixpkgs.lib.genAttrs supportedSystems; 21 | in 22 | { 23 | legacyPackages = forAllSystems (system: 24 | import self { 25 | nixpkgs = nixpkgs.legacyPackages.${system}; 26 | inherit system; 27 | }); 28 | 29 | packages = forAllSystems (system: { 30 | inherit (self.legacyPackages.${system}) default bld; 31 | }); 32 | 33 | devShells = forAllSystems (system: { 34 | default = self.legacyPackages.${system}.devShell; 35 | }); 36 | 37 | lib = import ./lib; 38 | 39 | checks = self.packages; 40 | 41 | hydraJobs = self.legacyPackages.x86_64-linux._flatten {}; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /lib/buildTree.nix: -------------------------------------------------------------------------------- 1 | { path 2 | , args 3 | }: 4 | let 5 | # copied from 6 | lib = { 7 | inherit (builtins) 8 | attrNames 9 | concatMap 10 | concatStringsSep 11 | hasAttr 12 | head 13 | isAttrs 14 | isString 15 | listToAttrs 16 | mapAttrs 17 | parseDrvName 18 | readDir 19 | substring 20 | tail 21 | ; 22 | 23 | 24 | splitString = 25 | let 26 | addContextFrom = a: b: builtins.substring 0 0 a + b; 27 | escape = list: builtins.replaceStrings list (map (c: "\\${c}") list); 28 | range = 29 | # First integer in the range 30 | first: 31 | # Last integer in the range 32 | last: 33 | if first > last then 34 | [ ] 35 | else 36 | builtins.genList (n: first + n) (last - first + 1); 37 | stringToCharacters = s: 38 | map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); 39 | escapeRegex = escape (stringToCharacters "\\[{()^$?*+|."); 40 | in 41 | _sep: _s: 42 | let 43 | sep = builtins.unsafeDiscardStringContext _sep; 44 | s = builtins.unsafeDiscardStringContext _s; 45 | splits = builtins.filter builtins.isString (builtins.split (escapeRegex sep) s); 46 | in 47 | map (v: addContextFrom _sep (addContextFrom _s v)) splits; 48 | 49 | getName = x: 50 | let 51 | parse = drv: (lib.parseDrvName drv).name; 52 | in 53 | if lib.isString x 54 | then parse x 55 | else x.pname or (parse x.name); 56 | 57 | getBin = pkg: 58 | if ! pkg ? outputSpecified || ! pkg.outputSpecified 59 | then pkg.bin or pkg.out or pkg 60 | else pkg; 61 | 62 | getExe = x: "${lib.getBin x}/bin/${x.meta.mainProgram or (lib.getName x)}"; 63 | 64 | isDerivation = x: x.type or null == "derivation"; 65 | 66 | filterAttrs = pred: set: 67 | lib.listToAttrs (lib.concatMap 68 | (name: 69 | let v = set.${name}; in 70 | if 71 | pred name v then [{ name = name; value = v; }] else [ ]) 72 | (lib.attrNames set)); 73 | 74 | getAttrByKey = name: lib.getAttrFromPath (lib.splitString "." name); 75 | 76 | getAttrFromPath = attrPath: 77 | let errorMsg = "cannot find attribute `" + lib.concatStringsSep "." attrPath + "'"; 78 | in lib.attrByPath attrPath (abort errorMsg); 79 | 80 | attrByPath = attrPath: default: e: 81 | let attr = lib.head attrPath; in 82 | if attrPath == [ ] then e 83 | else if e ? ${attr} 84 | then lib.attrByPath (lib.tail attrPath) default e.${attr} 85 | else default; 86 | }; 87 | 88 | # Like callPackage but: 89 | # * assumes ${path}/BUILD.nix 90 | # * is not overridable 91 | # * doesn't take an argument 92 | # * assumes the returned value is an attrset that we want to recurse into 93 | # 94 | # In the future it should also take a `self` argument, and maybe collect the 95 | # path. 96 | callBuildWith = args: path: 97 | import "${toString path}/BUILD.nix" args; 98 | 99 | root = { self = readBuildTree path; } // args; 100 | 101 | callBuild = callBuildWith root; 102 | 103 | # Generates a tree of attributes 104 | readBuildTree = path: 105 | # Used to check that the tree evaluation is lazy 106 | #assert builtins.trace "DEBUG: reading path ${toString path}" true; 107 | let 108 | dir = lib.readDir path; 109 | dirFilter = name: type: 110 | type == "directory" && 111 | ! (lib.hasAttr ".skip-subtree" dir) && 112 | lib.substring 0 1 name != "." # ignore folders starting with dot 113 | ; 114 | subDirs = lib.filterAttrs dirFilter dir; 115 | 116 | buildAttrs = if dir ? "BUILD.nix" then callBuild path else { }; 117 | 118 | op = name: _: readBuildTree "${toString path}/${toString name}"; 119 | 120 | subdirAttrs = lib.mapAttrs op subDirs; 121 | 122 | # TODO: fail if there is a collision in the keys 123 | # TODO: do not automatically recurse for everything 124 | attrs = { recurseForDerivations = true; } // subdirAttrs // buildAttrs; 125 | in 126 | attrs; 127 | 128 | flattenTree = import ./flattenTree.nix; 129 | in 130 | root.self // { 131 | _flatten = {}: flattenTree root.self; 132 | 133 | _list = path: lib.concatStringsSep "\n" (lib.attrNames (flattenTree (readBuildTree path))); 134 | 135 | _run = key: 136 | let 137 | val = lib.getAttrByKey key root.self; 138 | in 139 | if lib.isDerivation val then lib.getExe val 140 | else if !lib.isAttrs val then 141 | abort "${key} is not a derivation or attrs" 142 | else if ! val ? default then 143 | abort "${key} has not default package" 144 | else if !lib.isDerivation val.default then 145 | abort "${key}.default is not a derivation" 146 | else 147 | lib.getExe val.default; 148 | } 149 | 150 | 151 | -------------------------------------------------------------------------------- /lib/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | buildTree = import ./buildTree.nix; 3 | } 4 | -------------------------------------------------------------------------------- /lib/flattenTree.nix: -------------------------------------------------------------------------------- 1 | tree: 2 | let 3 | op = sum: path: val: 4 | let 5 | pathStr = builtins.concatStringsSep "/" path; 6 | in 7 | if (builtins.typeOf val) != "set" then 8 | # ignore that value 9 | # builtins.trace "${pathStr} is not of type set" 10 | sum 11 | else if val ? type && val.type == "derivation" then 12 | # builtins.trace "${pathStr} is a derivation" 13 | # we used to use the derivation outPath as the key, but that crashes Nix 14 | # so fallback on constructing a static key 15 | (sum // { 16 | "${pathStr}" = val; 17 | }) 18 | else if val ? recurseForDerivations && val.recurseForDerivations == true then 19 | # builtins.trace "${pathStr} is a recursive" 20 | # recurse into that attribute set 21 | (recurse sum path val) 22 | else 23 | # ignore that value 24 | # builtins.trace "${pathStr} is something else" 25 | sum 26 | ; 27 | 28 | recurse = sum: path: val: 29 | builtins.foldl' 30 | (sum: key: op sum (path ++ [ key ]) val.${key}) 31 | sum 32 | (builtins.attrNames val) 33 | ; 34 | in 35 | recurse { } [ ] tree 36 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | { system ? builtins.currentSystem }: 2 | (import ./. { inherit system; }).devShell 3 | -------------------------------------------------------------------------------- /treefmt.toml: -------------------------------------------------------------------------------- 1 | [formatter.nix] 2 | command = "nixpkgs-fmt" 3 | includes = ["*.nix"] 4 | 5 | [formatter.golang] 6 | command = "gofumpt" 7 | options = ["-w"] 8 | excludes = ["vendor/*"] 9 | includes = ["*.go"] 10 | --------------------------------------------------------------------------------