From b44c8c2aa95d3a49c838126f74afb191f12fa8e1 Mon Sep 17 00:00:00 2001 From: adisbladis Date: Sun, 29 May 2022 17:06:13 +0800 Subject: [PATCH 1/2] gomod2nix: Filter builder expressions from cli build --- default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/default.nix b/default.nix index 081cd27..95931bd 100644 --- a/default.nix +++ b/default.nix @@ -8,7 +8,7 @@ buildGoApplication { pname = "gomod2nix"; version = "0.1"; src = lib.cleanSourceWith { - filter = name: type: ! lib.hasSuffix "tests" name; + filter = name: type: (! lib.hasSuffix "tests" name) && (! lib.hasSuffix "builder" name); src = lib.cleanSource ./.; }; modules = ./gomod2nix.toml; From 212f269fafa53d9d0c0db5c43465d007984a9a39 Mon Sep 17 00:00:00 2001 From: adisbladis Date: Sun, 29 May 2022 19:15:32 +0800 Subject: [PATCH 2/2] Add preliminary support for private dependencies using builtins.fetchGit Using this API looks like: ``` nix buildGoApplication { srcOverrides = self: super: { "github.com/BurntSushi/toml" = super."github.com/BurntSushi/toml".override { private = true; }; }; } ``` Outstanding issues: - Nix has issues dealing with short revs ( https://github.com/NixOS/nix/issues/4694 ) - Param passing heuristics to fetchGit needs to be nailed down. --- builder/default.nix | 110 +++++++++++++++++++++++++++++--------- builder/parse-version.nix | 41 ++++++++++++++ builder/parser.nix | 12 ----- 3 files changed, 127 insertions(+), 36 deletions(-) create mode 100644 builder/parse-version.nix diff --git a/builder/default.nix b/builder/default.nix index 526c9fb..b28f4e4 100644 --- a/builder/default.nix +++ b/builder/default.nix @@ -10,28 +10,88 @@ , pkgs }: let + inherit (builtins) split elemAt filter typeOf; + + nixVersion = builtins.substring 0 3 builtins.nixVersion; + isNix24Plus = lib.versionAtLeast nixVersion "2.4"; parseGoMod = import ./parser.nix; + parseVersion = import ./parse-version.nix; removeExpr = refs: ''remove-references-to ${lib.concatMapStrings (ref: " -t ${ref}") refs}''; - fetchGoModule = - { hash - , goPackagePath + fetchGoModule = ( + lib.makeOverridable ( + { hash + , goPackagePath + , version + , private ? false + , go ? pkgs.go + }: + if private then + fetchGoModulePrivate + { + inherit goPackagePath version; + } else + stdenvNoCC.mkDerivation { + name = "${baseNameOf goPackagePath}_${version}"; + builder = ./fetch.sh; + inherit goPackagePath version; + nativeBuildInputs = [ go jq ]; + outputHashMode = "recursive"; + outputHashAlgo = null; + outputHash = hash; + SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt"; + impureEnvVars = lib.fetchers.proxyImpureEnvVars; + } + ) + ); + + # A "best effort" attempt at generalising fetching private repositories + # It's very likely that more advanced use cases needs to be done manually + # and that we'll need to have some UX for that. + # + # This version works for popular forges such as Github and Gitlab. + fetchGoModulePrivate = + { goPackagePath , version - , go ? pkgs.go }: - stdenvNoCC.mkDerivation { - name = "${baseNameOf goPackagePath}_${version}"; - builder = ./fetch.sh; - inherit goPackagePath version; - nativeBuildInputs = [ go jq ]; - outputHashMode = "recursive"; - outputHashAlgo = null; - outputHash = hash; - SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt"; - impureEnvVars = lib.fetchers.proxyImpureEnvVars; - }; + let + parsedVersion = parseVersion version; + + segments = filter (s: typeOf s != "list") (split "/" goPackagePath); + seg = elemAt segments; + domain = seg 0; + + url = "git@${domain}:${seg 1}/${seg 2}.git"; + sourceRoot = lib.concatStringsSep "/" (lib.drop 3 segments); + + src = builtins.fetchGit + { + inherit url; + } // lib.optionalAttrs isNix24Plus { + allRefs = true; + } // lib.optionalAttrs (parsedVersion.rev != "") { + # Nix has a bug handling short revs so this won't work. + inherit (parsedVersion) rev; + } // lib.optionalAttrs (parsedVersion.version != "v0.0.0") { + ref = "refs/tags/${parsedVersion.version}"; + }; + + in + if sourceRoot != "" then + stdenvNoCC.mkDerivation + { + name = "${baseNameOf goPackagePath}_${version}-wrapper"; + inherit src; + dontConfigure = true; + dontBuild = true; + dontFixup = true; + installPhase = '' + cd "${sourceRoot}" + cp -a . $out + ''; + } else src; buildGoApplication = { modules @@ -43,6 +103,7 @@ let , allowGoReference ? false , meta ? { } , passthru ? { } + , srcOverrides ? self: super: { } , ... }@attrs: let @@ -69,15 +130,16 @@ let nativeBuildInputs = [ go ]; json = builtins.toJSON modulesStruct; - sources = builtins.toJSON ( - lib.mapAttrs - (goPackagePath: meta: fetchGoModule { - goPackagePath = meta.replaced or goPackagePath; - inherit (meta) version hash; - inherit go; - }) - modulesStruct.mod - ); + sources = builtins.toJSON (builtins.removeAttrs + ((lib.makeExtensible (self: ( + lib.mapAttrs + (goPackagePath: meta: fetchGoModule { + goPackagePath = meta.replaced or goPackagePath; + inherit (meta) version hash; + inherit go; + }) + modulesStruct.mod + ))).extend srcOverrides) [ "extend" "__unfix__" ]); passAsFile = [ "json" "sources" ]; } diff --git a/builder/parse-version.nix b/builder/parse-version.nix new file mode 100644 index 0000000..4a52106 --- /dev/null +++ b/builder/parse-version.nix @@ -0,0 +1,41 @@ +let + inherit (builtins) elemAt match hasAttr removeAttrs; +in +ver: +removeAttrs + (builtins.foldl' (acc: f: if hasAttr "rest" acc then f acc else acc) + { + version = ""; + rev = ""; + versionSuffix = ""; + date = ""; + rest = ver; + } [ + (acc: + let + m = match "([^-]+)-(.*)" acc.rest; + e = elemAt m; + in + if m != null then { + version = e 0; + rest = e 1; + } else removeAttrs acc [ "rest" ] // { + version = ver; + }) + (acc: + let + m = elemAt (match "(.*)-(.*)" acc.rest); + in + acc // { + rev = m 1; + rest = m 0; + }) + (acc: + let + m = elemAt (match "(.*)\\.(.*)" acc.rest); + in + acc // { + versionSuffix = m 0; + date = m 1; + }) + ]) [ "rest" ] diff --git a/builder/parser.nix b/builder/parser.nix index eb6f75e..e711921 100644 --- a/builder/parser.nix +++ b/builder/parser.nix @@ -98,18 +98,6 @@ let } ); - parseVersion = ver: - let - m = elemAt (match "([^-]+)-?([^-]*)-?([^-]*)" ver); - v = elemAt (match "([^+]+)\\+?(.*)" (m 0)); - in - { - version = v 0; - versionSuffix = v 1; - date = m 1; - rev = m 2; - }; - parseReplace = data: ( data // { replace =