From 2034c858bd4df8180233069c52691668072a5b5c Mon Sep 17 00:00:00 2001 From: adisbladis Date: Thu, 23 Jul 2020 11:11:31 +0200 Subject: [PATCH] Create in-sandbox builder for env --- default.nix | 39 ++++++++-------- go_no_vendor_checks.patch | 13 ++++++ symlink.go | 94 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 21 deletions(-) create mode 100644 go_no_vendor_checks.patch create mode 100644 symlink.go diff --git a/default.nix b/default.nix index 4cd795f..47ba328 100644 --- a/default.nix +++ b/default.nix @@ -14,6 +14,7 @@ let buildGoApplication = { modules + , src , CGO_ENABLED ? "0" , nativeBuildInputs ? [] , allowGoReference ? false @@ -23,34 +24,29 @@ let }@attrs: let modulesStruct = builtins.fromTOML (builtins.readFile modules); - # TODO: This is a giant inefficient hack - # Replace this with something that's _like_ buildEnv but doesn't need a - # runCommand per input - vendorEnv = buildEnv { - # Better method for this? - ignoreCollisions = true; + vendorEnv = runCommand "vendor-env" { + nativeBuildInputs = [ pkgs.go ]; + json = builtins.toJSON modulesStruct; - # nativeBuildInputs = [ go ]; - - name = "vendor-env"; - paths = lib.mapAttrsToList (goPackagePath: meta: let + sources = builtins.toJSON (lib.mapAttrs (goPackagePath: meta: let src = fetchgit { inherit (meta.fetch) url sha256 rev; fetchSubmodules = true; }; - path = goPackagePath; srcPath = "${src}/${meta.relPath or ""}"; - mkCommand = outpath: '' - mkdir -p $out/$(dirname ${outpath}) - ln -s ${srcPath} $out/${outpath} - ''; + in srcPath) modulesStruct); - in runCommand "${src.name}-env" {} '' - ${mkCommand goPackagePath} - ${if lib.hasAttr "vendorPath" meta then (mkCommand meta.vendorPath) else ""} - '') modulesStruct; + passAsFile = [ "json" "sources" ]; + } ('' + mkdir vendor - }; + export GOCACHE=$TMPDIR/go-cache + export GOPATH="$TMPDIR/go" + + go run ${./symlink.go} + + mv vendor $out + ''); removeReferences = [ ] ++ lib.optional (!allowGoReference) go; @@ -58,7 +54,6 @@ let nativeBuildInputs = [ removeReferencesTo go ] ++ nativeBuildInputs; inherit (go) GOOS GOARCH; - inherit CGO_ENABLED; GO_NO_VENDOR_CHECKS = "1"; @@ -187,6 +182,8 @@ in buildGoApplication { pname = "dummyapp"; version = "0.1"; + CGO_ENABLED = "1"; + src = ./testdata/vuls; modules = ./testdata/vuls/gomod2nix.toml; diff --git a/go_no_vendor_checks.patch b/go_no_vendor_checks.patch new file mode 100644 index 0000000..e2cebf4 --- /dev/null +++ b/go_no_vendor_checks.patch @@ -0,0 +1,13 @@ +diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go +index 71f68efbcc..3c566d04dd 100644 +--- a/src/cmd/go/internal/modload/vendor.go ++++ b/src/cmd/go/internal/modload/vendor.go +@@ -133,7 +133,7 @@ func checkVendorConsistency() { + readVendorList() + + pre114 := false +- if modFile.Go == nil || semver.Compare("v"+modFile.Go.Version, "v1.14") < 0 { ++ if modFile.Go == nil || semver.Compare("v"+modFile.Go.Version, "v1.14") < 0 || (os.Getenv("GO_NO_VENDOR_CHECKS") == "1" && len(vendorMeta) == 0) { + // Go versions before 1.14 did not include enough information in + // vendor/modules.txt to check for consistency. + // If we know that we're on an earlier version, relax the consistency check. diff --git a/symlink.go b/symlink.go new file mode 100644 index 0000000..b10ded1 --- /dev/null +++ b/symlink.go @@ -0,0 +1,94 @@ +package main + +import ( + "encoding/json" + "io/ioutil" + "os" + "path/filepath" + "sort" +) + +type fetchInfo struct { + Type string `toml:"type"` + URL string `toml:"url"` + Rev string `toml:"rev"` + Sha256 string `toml:"sha256"` +} + +type packageT struct { + SumVersion string `toml:"sumVersion"` + RelPath string `toml:"relPath,omitempty"` + VendorPath string `toml:"vendorPath,omitempty"` + Fetch *fetchInfo `toml:"fetch"` +} + +func main() { + + pkgs := make(map[string]*packageT) + sources := make(map[string]string) + + b, err := ioutil.ReadFile(os.Getenv("sourcesPath")) + if err != nil { + panic(err) + } + + err = json.Unmarshal(b, &sources) + if err != nil { + panic(err) + } + + b, err = ioutil.ReadFile(os.Getenv("jsonPath")) + if err != nil { + panic(err) + } + + err = json.Unmarshal(b, &pkgs) + if err != nil { + panic(err) + } + + keys := make([]string, 0, len(pkgs)) + for key := range pkgs { + keys = append(keys, key) + } + sort.Strings(keys) + + // Iterate, in reverse order + for i := len(keys) - 1; i >= 0; i-- { + key := keys[i] + src := sources[key] + pkg := pkgs[key] + + paths := []string{key} + if pkg.VendorPath != "" { + paths = append(paths, pkg.VendorPath) + } + + for _, path := range paths { + + vendorDir := filepath.Join("vendor", filepath.Dir(path)) + os.MkdirAll(vendorDir, 0755) + + if _, err := os.Stat(filepath.Join("vendor", path)); err == nil { + files, err := ioutil.ReadDir(src) + if err != nil { + panic(err) + } + + for _, f := range files { + os.Symlink(filepath.Join(src, f.Name()), filepath.Join("vendor", path, f.Name())) + } + + continue + } + + // If the file doesn't already exist, just create a simple symlink + err := os.Symlink(src, filepath.Join("vendor", path)) + if err != nil { + panic(err) + } + + } + } + +}