Add Nix packaging
This commit is contained in:
parent
9ce0d22c99
commit
aac8ee19d7
8 changed files with 920 additions and 0 deletions
11
README.md
11
README.md
|
@ -44,6 +44,17 @@ Bottin requires go 1.13 or later.
|
|||
To build Bottin, clone this repository outside of your `$GOPATH`.
|
||||
Then, run `make` in the root of the repo.
|
||||
|
||||
## Releasing
|
||||
|
||||
```bash
|
||||
nix-build -A bin
|
||||
nix-build -A docker
|
||||
```
|
||||
|
||||
```bash
|
||||
docker load < $(nix-build -A docker)
|
||||
docker push ???
|
||||
```
|
||||
|
||||
## Server initialization
|
||||
|
||||
|
|
48
default.nix
Normal file
48
default.nix
Normal file
|
@ -0,0 +1,48 @@
|
|||
let
|
||||
pkgsSrc = fetchTarball {
|
||||
# As of 2022-07-19
|
||||
url = "https://github.com/NixOS/nixpkgs/archive/d2db10786f27619d5519b12b03fb10dc8ca95e59.tar.gz";
|
||||
sha256 = "0s9gigs3ylnq5b94rfcmxvrmmr3kzhs497gksajf638d5bv7zcl5";
|
||||
};
|
||||
pkgs = import pkgsSrc {
|
||||
overlays = [
|
||||
(self: super: {
|
||||
gomod = super.callPackage ./nix/builder { };
|
||||
})
|
||||
];
|
||||
};
|
||||
in rec {
|
||||
bin = pkgs.gomod.buildGoApplication {
|
||||
pname = "bottin-bin";
|
||||
version = "0.1.0";
|
||||
src = builtins.filterSource
|
||||
(path: type: (builtins.match ".*/test/.*\\.(go|sum|mod)" path) == null)
|
||||
./.;
|
||||
modules = ./gomod2nix.toml;
|
||||
|
||||
CGO_ENABLED=0;
|
||||
|
||||
meta = with pkgs.lib; {
|
||||
description = "Interface web pour gérer le LDAP: changer son mot de passe, ses infos de profil, inviter des gens, administration";
|
||||
homepage = "https://git.deuxfleurs.fr/Deuxfleurs/guichet";
|
||||
license = licenses.gpl3Plus;
|
||||
platforms = platforms.linux;
|
||||
};
|
||||
};
|
||||
pkg = pkgs.stdenv.mkDerivation {
|
||||
pname = "bottin";
|
||||
version = "0.1.0";
|
||||
unpackPhase = "true";
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/
|
||||
cp ${bin}/bin/bottin $out/bottin
|
||||
'';
|
||||
};
|
||||
docker = pkgs.dockerTools.buildImage {
|
||||
name = "dxflrs/bottin";
|
||||
config = {
|
||||
Cmd = [ "${pkg}/bottin" ];
|
||||
};
|
||||
};
|
||||
}
|
153
gomod2nix.toml
Normal file
153
gomod2nix.toml
Normal file
|
@ -0,0 +1,153 @@
|
|||
schema = 3
|
||||
|
||||
[mod]
|
||||
[mod."github.com/armon/circbuf"]
|
||||
version = "v0.0.0-20150827004946-bbbad097214e"
|
||||
hash = "sha256-klQjllsJZqZ2KPNx1mZT9XP+UAJkuBhmTnZdNlAflEM="
|
||||
[mod."github.com/armon/go-metrics"]
|
||||
version = "v0.0.0-20180917152333-f0300d1749da"
|
||||
hash = "sha256-+zqX1hlJgc+IrXRzBQDMhR8GYQdc0Oj6PiIDfctgh44="
|
||||
[mod."github.com/armon/go-radix"]
|
||||
version = "v0.0.0-20180808171621-7fddfc383310"
|
||||
hash = "sha256-ZHU4pyBqHHRuQJuYr2K+LqeAnLX9peX07cmSYK+GDHk="
|
||||
[mod."github.com/bgentry/speakeasy"]
|
||||
version = "v0.1.0"
|
||||
hash = "sha256-Gt1vj6CFovLnO6wX5u2O4UfecY9V2J9WGw1ez4HMrgk="
|
||||
[mod."github.com/davecgh/go-spew"]
|
||||
version = "v1.1.1"
|
||||
hash = "sha256-nhzSUrE1fCkN0+RL04N4h8jWmRFPPPWbCuDc7Ss0akI="
|
||||
[mod."github.com/fatih/color"]
|
||||
version = "v1.7.0"
|
||||
hash = "sha256-4In7ef7it7d+6oGUJ3pkD0V+lsL40hVtYdy2KD2ovn0="
|
||||
[mod."github.com/google/btree"]
|
||||
version = "v0.0.0-20180813153112-4030bb1f1f0c"
|
||||
hash = "sha256-5gr0RMnlvrzCke3kwpkf92WvW3x5nnKZesoulyoYRC0="
|
||||
[mod."github.com/google/uuid"]
|
||||
version = "v1.1.1"
|
||||
hash = "sha256-66PXC/RCPUyhS9PhkIPQFR3tbM2zZYDNPGXN7JJj3UE="
|
||||
[mod."github.com/hashicorp/consul/api"]
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-fMORNFAWK2GkRbBl/KzNHrvtCfwz/7P66HzDaE4GnuE="
|
||||
[mod."github.com/hashicorp/consul/sdk"]
|
||||
version = "v0.3.0"
|
||||
hash = "sha256-lF47JPGfmeGjpuQw9VSNs2Mi+G7FQLKrrHteX3iXfpU="
|
||||
[mod."github.com/hashicorp/errwrap"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-LGSLrefkABG1kH1i+GUWiD2/ggJxiZEJ+D2YNbhZjmo="
|
||||
[mod."github.com/hashicorp/go-cleanhttp"]
|
||||
version = "v0.5.1"
|
||||
hash = "sha256-c54zcHr9THj3MQk7hrDQcpjOcQi1MvXZ4Kpin6EbfR4="
|
||||
[mod."github.com/hashicorp/go-immutable-radix"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-JmNxdGaJG63Ty/sVnPjqvTyA4/k5wkzZ/QvpMK2uduw="
|
||||
[mod."github.com/hashicorp/go-msgpack"]
|
||||
version = "v0.5.3"
|
||||
hash = "sha256-2OUYjD/Jt12TFBrtH0wRqg+lzRljDxSIhk2CqBLUczo="
|
||||
[mod."github.com/hashicorp/go-multierror"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-iXzjerl96o7QDiSwQjbak8R/t+YzZeoUqm59TCmy3gI="
|
||||
[mod."github.com/hashicorp/go-rootcerts"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-4NZJAT5/vocyto+dv6FmW4kFiYldmNvewowsYK/LiTI="
|
||||
[mod."github.com/hashicorp/go-sockaddr"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-orG+SHVsp5lgNRCErmhMLABVFQ3ZWfYIJ/4LTFzlvao="
|
||||
[mod."github.com/hashicorp/go-syslog"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-YRuq6oPMwAFVY7mvwpMDvZqGwNnb5CjBYyKI/x5mbCc="
|
||||
[mod."github.com/hashicorp/go-uuid"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-s1wIvBu37z4U3qK9sdUR1CtbD39N6RwfX4HgDCpCa0s="
|
||||
[mod."github.com/hashicorp/go.net"]
|
||||
version = "v0.0.1"
|
||||
hash = "sha256-JKal3E+wPO+Hk838opKV4HHKB4O72Xy+77ncXlLkWRk="
|
||||
[mod."github.com/hashicorp/golang-lru"]
|
||||
version = "v0.5.0"
|
||||
hash = "sha256-Lo0UyOZQ89iK0Ui3Hfk5VkWqxEzLw6Lclq4EM8VlYoo="
|
||||
[mod."github.com/hashicorp/logutils"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-e8t8Dm8sp/PzKClN1TOmFcrTAWNh4mZHSW7cAjVx3Bw="
|
||||
[mod."github.com/hashicorp/mdns"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-ravx4tklQG43OEjPiJn68iJM9ODZ6hgU0idFCEOiJGM="
|
||||
[mod."github.com/hashicorp/memberlist"]
|
||||
version = "v0.1.3"
|
||||
hash = "sha256-IsxqevYulPt+2VGtlq068Jyq1YfIk4Ohh9TgakIGxnc="
|
||||
[mod."github.com/hashicorp/serf"]
|
||||
version = "v0.8.2"
|
||||
hash = "sha256-diRxWOouFLTO75f2E9NlrKgie/qsT+gOOrrbf4tACHw="
|
||||
[mod."github.com/jsimonetti/pwscheme"]
|
||||
version = "v0.0.0-20220125093853-4d9895f5db73"
|
||||
hash = "sha256-YF3RKU/4CWvLPgGzUd7Hk/2+41OUFuRWZgzQuqcsKg0="
|
||||
[mod."github.com/konsorten/go-windows-terminal-sequences"]
|
||||
version = "v1.0.1"
|
||||
hash = "sha256-Nwp+Cza9dIu3ogVGip6wyOjWwwaq+2hU3eYIe4R7kNE="
|
||||
[mod."github.com/mattn/go-colorable"]
|
||||
version = "v0.0.9"
|
||||
hash = "sha256-fVPF8VxbdggLAZnaexMl6Id1WjXKImzVySxKfa+ukts="
|
||||
[mod."github.com/mattn/go-isatty"]
|
||||
version = "v0.0.3"
|
||||
hash = "sha256-9ogEEd8/kl/dImldzdBmTFdepvB0dVXEzN4o8bEqhBs="
|
||||
[mod."github.com/miekg/dns"]
|
||||
version = "v1.0.14"
|
||||
hash = "sha256-OeijUgBaEmDapclTxfvjIqrjh4qZu3+DQpHelGGI4aA="
|
||||
[mod."github.com/mitchellh/cli"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-4nG7AhRcjTRCwUCdnaNaFrAKDxEEoiihaCA4lk+uM8U="
|
||||
[mod."github.com/mitchellh/go-homedir"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-eGmBNNTuDSMwicjTNgB54IEJuK1tgOLDJ3NHTpQCHzg="
|
||||
[mod."github.com/mitchellh/go-testing-interface"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-/Dpv/4i5xuK8hDH+q8YTdF6Jg6NNtfO4Wqig2JCWgrY="
|
||||
[mod."github.com/mitchellh/gox"]
|
||||
version = "v0.4.0"
|
||||
hash = "sha256-GV3LYxzJt8YVbnSac2orlj2QR3MX/YIDrLkSkPhsjuA="
|
||||
[mod."github.com/mitchellh/iochan"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-b5Tp7cw/e8mL++IjsebbmKWXtb9Hrzu4Fc6M4tZKFhU="
|
||||
[mod."github.com/mitchellh/mapstructure"]
|
||||
version = "v1.1.2"
|
||||
hash = "sha256-OU9HZYHtl0qaqMFd84w7snkkRuRY6UMSsfCnL5HYdw0="
|
||||
[mod."github.com/pascaldekloe/goe"]
|
||||
version = "v0.0.0-20180627143212-57f6aae5913c"
|
||||
hash = "sha256-2KUjqrEC/BwkTZRxImazcI/C3H7QmXfNrlt8slwdDbc="
|
||||
[mod."github.com/pkg/errors"]
|
||||
version = "v0.8.1"
|
||||
hash = "sha256-oe3iddfoLRwpC3ki5fifHf2ZFprtg99iNak50shiuDw="
|
||||
[mod."github.com/pmezard/go-difflib"]
|
||||
version = "v1.0.0"
|
||||
hash = "sha256-/FtmHnaGjdvEIKAJtrUfEhV7EVo5A/eYrtdnUkuxLDA="
|
||||
[mod."github.com/posener/complete"]
|
||||
version = "v1.1.1"
|
||||
hash = "sha256-heyPMSBzVlx7ZKgTyzl/xmUfZw3EZCcvGFGrRMIbIr8="
|
||||
[mod."github.com/ryanuber/columnize"]
|
||||
version = "v0.0.0-20160712163229-9b3edd62028f"
|
||||
hash = "sha256-RLUQcU6Z03upKe08v6rjn9/tkyrQsgmpdEmBtWaLQfk="
|
||||
[mod."github.com/sean-/seed"]
|
||||
version = "v0.0.0-20170313163322-e2103e2c3529"
|
||||
hash = "sha256-RQQTjvf8Y91jP5FGOyEnGMFw7zCrcSnUU4eH2CXKkT4="
|
||||
[mod."github.com/sirupsen/logrus"]
|
||||
version = "v1.4.2"
|
||||
hash = "sha256-3QzWUsapCmg3F7JqUuINT3/UG097uzLff6iCcCgQ43o="
|
||||
[mod."github.com/stretchr/objx"]
|
||||
version = "v0.1.1"
|
||||
hash = "sha256-HdGVZCuy7VprC5W9UxGbDmXqsKADMjpEDht7ilGVLco="
|
||||
[mod."github.com/stretchr/testify"]
|
||||
version = "v1.3.0"
|
||||
hash = "sha256-+mSebBNccNcxbY462iKTNTWmd5ZuUkUqFebccn3EtIA="
|
||||
[mod."golang.org/x/crypto"]
|
||||
version = "v0.0.0-20200604202706-70a84ac30bf9"
|
||||
hash = "sha256-I5ov2lV6ubB3H3pn6DFN1VPLyxeLfPUaOx2PJ9K1KH8="
|
||||
[mod."golang.org/x/net"]
|
||||
version = "v0.0.0-20190404232315-eb5bcb51f2a3"
|
||||
hash = "sha256-kwP+BDfPsZEeeceyg4H5LgdTDT8O8YWbkpCkpyuPJJo="
|
||||
[mod."golang.org/x/sync"]
|
||||
version = "v0.0.0-20181221193216-37e7f081c4d4"
|
||||
hash = "sha256-FUpv9bmGLDEjCxXdvR0CRDqOKRY0xrHRPzOsyQyvYK0="
|
||||
[mod."golang.org/x/sys"]
|
||||
version = "v0.0.0-20190422165155-953cdadca894"
|
||||
hash = "sha256-YkQjSZaiVFxrmXYSKmqrGeIO3RZ95fc3dWyCaR+SosY="
|
||||
[mod."golang.org/x/text"]
|
||||
version = "v0.3.0"
|
||||
hash = "sha256-0FFbaxF1ZuAQF3sCcA85e8MO6prFeHint36inija4NY="
|
387
nix/builder/default.nix
Normal file
387
nix/builder/default.nix
Normal file
|
@ -0,0 +1,387 @@
|
|||
{ stdenv
|
||||
, stdenvNoCC
|
||||
, runCommand
|
||||
, buildEnv
|
||||
, lib
|
||||
, fetchgit
|
||||
, removeReferencesTo
|
||||
, jq
|
||||
, cacert
|
||||
, pkgs
|
||||
, pkgsBuildBuild
|
||||
}:
|
||||
let
|
||||
|
||||
inherit (builtins) substring toJSON hasAttr trace split readFile elemAt;
|
||||
inherit (lib)
|
||||
concatStringsSep replaceStrings removePrefix optionalString pathExists
|
||||
optional concatMapStrings fetchers filterAttrs mapAttrs mapAttrsToList
|
||||
warnIf optionalAttrs platforms
|
||||
;
|
||||
|
||||
parseGoMod = import ./parser.nix;
|
||||
|
||||
removeExpr = refs: ''remove-references-to ${concatMapStrings (ref: " -t ${ref}") refs}'';
|
||||
|
||||
# Internal only build-time attributes
|
||||
internal =
|
||||
let
|
||||
mkInternalPkg = name: src: pkgsBuildBuild.runCommand "gomod2nix-${name}"
|
||||
{
|
||||
inherit (pkgsBuildBuild.go) GOOS GOARCH;
|
||||
nativeBuildInputs = [ pkgsBuildBuild.go ];
|
||||
} ''
|
||||
export HOME=$(mktemp -d)
|
||||
cp ${src} src.go
|
||||
go build -o $out src.go
|
||||
'';
|
||||
in
|
||||
{
|
||||
|
||||
# Create a symlink tree of vendored sources
|
||||
symlink = mkInternalPkg "symlink" ./symlink/symlink.go;
|
||||
|
||||
# Install development dependencies from tools.go
|
||||
install = mkInternalPkg "symlink" ./install/install.go;
|
||||
|
||||
};
|
||||
|
||||
fetchGoModule =
|
||||
{ hash
|
||||
, 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 = fetchers.proxyImpureEnvVars ++ [ "GOPROXY" ];
|
||||
};
|
||||
|
||||
mkVendorEnv =
|
||||
{ go
|
||||
, modulesStruct
|
||||
, localReplaceCommands ? [ ]
|
||||
, defaultPackage ? ""
|
||||
, goMod
|
||||
, pwd
|
||||
}:
|
||||
let
|
||||
localReplaceCommands =
|
||||
let
|
||||
localReplaceAttrs = filterAttrs (n: v: hasAttr "path" v) goMod.replace;
|
||||
commands = (
|
||||
mapAttrsToList
|
||||
(name: value: (
|
||||
''
|
||||
mkdir -p $(dirname vendor/${name})
|
||||
ln -s ${pwd + "/${value.path}"} vendor/${name}
|
||||
''
|
||||
))
|
||||
localReplaceAttrs);
|
||||
in
|
||||
if goMod != null then commands else [ ];
|
||||
|
||||
sources = mapAttrs
|
||||
(goPackagePath: meta: fetchGoModule {
|
||||
goPackagePath = meta.replaced or goPackagePath;
|
||||
inherit (meta) version hash;
|
||||
inherit go;
|
||||
})
|
||||
modulesStruct.mod;
|
||||
in
|
||||
runCommand "vendor-env"
|
||||
{
|
||||
nativeBuildInputs = [ go ];
|
||||
json = toJSON (filterAttrs (n: _: n != defaultPackage) modulesStruct.mod);
|
||||
|
||||
sources = toJSON (filterAttrs (n: _: n != defaultPackage) sources);
|
||||
|
||||
passthru = {
|
||||
inherit sources;
|
||||
};
|
||||
|
||||
passAsFile = [ "json" "sources" ];
|
||||
}
|
||||
(
|
||||
''
|
||||
mkdir vendor
|
||||
|
||||
export GOCACHE=$TMPDIR/go-cache
|
||||
export GOPATH="$TMPDIR/go"
|
||||
|
||||
${internal.symlink}
|
||||
${concatStringsSep "\n" localReplaceCommands}
|
||||
|
||||
mv vendor $out
|
||||
''
|
||||
);
|
||||
|
||||
# Select Go attribute based on version specified in go.mod
|
||||
selectGo = attrs: goMod: attrs.go or (if goMod == null then pkgs.go else
|
||||
(
|
||||
let
|
||||
goVersion = goMod.go;
|
||||
goAttr = "go_" + (replaceStrings [ "." ] [ "_" ] goVersion);
|
||||
in
|
||||
(
|
||||
if hasAttr goAttr pkgs then pkgs.${goAttr}
|
||||
else trace "go.mod specified Go version ${goVersion} but doesn't exist. Falling back to ${pkgs.go.version}." pkgs.go
|
||||
)
|
||||
));
|
||||
|
||||
# Strip the rubbish that Go adds to versions, and fall back to a version based on the date if it's a placeholder value
|
||||
stripVersion = version:
|
||||
let
|
||||
parts = elemAt (split "(\\+|-)" (removePrefix "v" version));
|
||||
v = parts 0;
|
||||
d = parts 2;
|
||||
in
|
||||
if v != "0.0.0" then v else "unstable-" + (concatStringsSep "-" [
|
||||
(substring 0 4 d)
|
||||
(substring 4 2 d)
|
||||
(substring 6 2 d)
|
||||
]);
|
||||
|
||||
mkGoEnv =
|
||||
{ pwd
|
||||
}@attrs:
|
||||
let
|
||||
goMod = parseGoMod (readFile "${toString pwd}/go.mod");
|
||||
modulesStruct = fromTOML (readFile "${toString pwd}/gomod2nix.toml");
|
||||
|
||||
go = selectGo attrs goMod;
|
||||
|
||||
vendorEnv = mkVendorEnv {
|
||||
inherit go modulesStruct pwd goMod;
|
||||
};
|
||||
|
||||
in
|
||||
stdenv.mkDerivation (removeAttrs attrs [ "pwd" ] // {
|
||||
name = "${baseNameOf goMod.module}-env";
|
||||
|
||||
dontUnpack = true;
|
||||
dontConfigure = true;
|
||||
dontInstall = true;
|
||||
|
||||
propagatedNativeBuildInputs = [ go ];
|
||||
|
||||
GO_NO_VENDOR_CHECKS = "1";
|
||||
|
||||
GO111MODULE = "on";
|
||||
GOFLAGS = "-mod=vendor";
|
||||
|
||||
preferLocalBuild = true;
|
||||
|
||||
buildPhase = ''
|
||||
mkdir $out
|
||||
|
||||
export GOCACHE=$TMPDIR/go-cache
|
||||
export GOPATH="$out"
|
||||
export GOSUMDB=off
|
||||
export GOPROXY=off
|
||||
|
||||
'' + optionalString (pathExists (pwd + "/tools.go")) ''
|
||||
mkdir source
|
||||
cp ${pwd + "/go.mod"} source/go.mod
|
||||
cp ${pwd + "/go.sum"} source/go.sum
|
||||
cp ${pwd + "/tools.go"} source/tools.go
|
||||
cd source
|
||||
ln -s ${vendorEnv} vendor
|
||||
|
||||
${internal.install}
|
||||
'';
|
||||
});
|
||||
|
||||
buildGoApplication =
|
||||
{ modules ? pwd + "/gomod2nix.toml"
|
||||
, src ? pwd
|
||||
, pwd ? null
|
||||
, nativeBuildInputs ? [ ]
|
||||
, allowGoReference ? false
|
||||
, meta ? { }
|
||||
, passthru ? { }
|
||||
, tags ? [ ]
|
||||
|
||||
# needed for buildFlags{,Array} warning
|
||||
, buildFlags ? ""
|
||||
, buildFlagsArray ? ""
|
||||
|
||||
, ...
|
||||
}@attrs:
|
||||
let
|
||||
modulesStruct = fromTOML (readFile modules);
|
||||
|
||||
goModPath = "${toString pwd}/go.mod";
|
||||
|
||||
goMod =
|
||||
if pwd != null && pathExists goModPath
|
||||
then parseGoMod (readFile goModPath)
|
||||
else null;
|
||||
|
||||
go = selectGo attrs goMod;
|
||||
|
||||
removeReferences = [ ] ++ optional (!allowGoReference) go;
|
||||
|
||||
defaultPackage = modulesStruct.goPackagePath or "";
|
||||
|
||||
vendorEnv = mkVendorEnv {
|
||||
inherit go modulesStruct defaultPackage goMod pwd;
|
||||
};
|
||||
|
||||
in
|
||||
warnIf (buildFlags != "" || buildFlagsArray != "")
|
||||
"Use the `ldflags` and/or `tags` attributes instead of `buildFlags`/`buildFlagsArray`"
|
||||
stdenv.mkDerivation
|
||||
(optionalAttrs (defaultPackage != "")
|
||||
{
|
||||
pname = attrs.pname or baseNameOf defaultPackage;
|
||||
version = stripVersion (modulesStruct.mod.${defaultPackage}).version;
|
||||
src = vendorEnv.passthru.sources.${defaultPackage};
|
||||
} // optionalAttrs (hasAttr "subPackages" modulesStruct) {
|
||||
subPackages = modulesStruct.subPackages;
|
||||
} // attrs // {
|
||||
nativeBuildInputs = [ removeReferencesTo go ] ++ nativeBuildInputs;
|
||||
|
||||
inherit (go) GOOS GOARCH;
|
||||
|
||||
GO_NO_VENDOR_CHECKS = "1";
|
||||
|
||||
GO111MODULE = "on";
|
||||
GOFLAGS = "-mod=vendor";
|
||||
|
||||
configurePhase = attrs.configurePhase or ''
|
||||
runHook preConfigure
|
||||
|
||||
export GOCACHE=$TMPDIR/go-cache
|
||||
export GOPATH="$TMPDIR/go"
|
||||
export GOSUMDB=off
|
||||
export GOPROXY=off
|
||||
cd "$modRoot"
|
||||
if [ -n "${vendorEnv}" ]; then
|
||||
rm -rf vendor
|
||||
ln -s ${vendorEnv} vendor
|
||||
fi
|
||||
|
||||
runHook postConfigure
|
||||
'';
|
||||
|
||||
buildPhase = attrs.buildPhase or ''
|
||||
runHook preBuild
|
||||
|
||||
exclude='\(/_\|examples\|Godeps\|testdata'
|
||||
if [[ -n "$excludedPackages" ]]; then
|
||||
IFS=' ' read -r -a excludedArr <<<$excludedPackages
|
||||
printf -v excludedAlternates '%s\\|' "''${excludedArr[@]}"
|
||||
excludedAlternates=''${excludedAlternates%\\|} # drop final \| added by printf
|
||||
exclude+='\|'"$excludedAlternates"
|
||||
fi
|
||||
exclude+='\)'
|
||||
|
||||
buildGoDir() {
|
||||
local d; local cmd;
|
||||
cmd="$1"
|
||||
d="$2"
|
||||
. $TMPDIR/buildFlagsArray
|
||||
local OUT
|
||||
if ! OUT="$(go $cmd $buildFlags "''${buildFlagsArray[@]}" ''${tags:+-tags=${concatStringsSep "," tags}} ''${ldflags:+-ldflags="$ldflags"} -v -p $NIX_BUILD_CORES $d 2>&1)"; then
|
||||
if echo "$OUT" | grep -qE 'imports .*?: no Go files in'; then
|
||||
echo "$OUT" >&2
|
||||
return 1
|
||||
fi
|
||||
if ! echo "$OUT" | grep -qE '(no( buildable| non-test)?|build constraints exclude all) Go (source )?files'; then
|
||||
echo "$OUT" >&2
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
if [ -n "$OUT" ]; then
|
||||
echo "$OUT" >&2
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
getGoDirs() {
|
||||
local type;
|
||||
type="$1"
|
||||
if [ -n "$subPackages" ]; then
|
||||
echo "$subPackages" | sed "s,\(^\| \),\1./,g"
|
||||
else
|
||||
find . -type f -name \*$type.go -exec dirname {} \; | grep -v "/vendor/" | sort --unique | grep -v "$exclude"
|
||||
fi
|
||||
}
|
||||
|
||||
if (( "''${NIX_DEBUG:-0}" >= 1 )); then
|
||||
buildFlagsArray+=(-x)
|
||||
fi
|
||||
|
||||
if [ ''${#buildFlagsArray[@]} -ne 0 ]; then
|
||||
declare -p buildFlagsArray > $TMPDIR/buildFlagsArray
|
||||
else
|
||||
touch $TMPDIR/buildFlagsArray
|
||||
fi
|
||||
if [ -z "$enableParallelBuilding" ]; then
|
||||
export NIX_BUILD_CORES=1
|
||||
fi
|
||||
for pkg in $(getGoDirs ""); do
|
||||
echo "Building subPackage $pkg"
|
||||
buildGoDir install "$pkg"
|
||||
done
|
||||
'' + optionalString (stdenv.hostPlatform != stdenv.buildPlatform) ''
|
||||
# normalize cross-compiled builds w.r.t. native builds
|
||||
(
|
||||
dir=$GOPATH/bin/${go.GOOS}_${go.GOARCH}
|
||||
if [[ -n "$(shopt -s nullglob; echo $dir/*)" ]]; then
|
||||
mv $dir/* $dir/..
|
||||
fi
|
||||
if [[ -d $dir ]]; then
|
||||
rmdir $dir
|
||||
fi
|
||||
)
|
||||
'' + ''
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
doCheck = attrs.doCheck or true;
|
||||
checkPhase = attrs.checkPhase or ''
|
||||
runHook preCheck
|
||||
|
||||
for pkg in $(getGoDirs test); do
|
||||
buildGoDir test $checkFlags "$pkg"
|
||||
done
|
||||
|
||||
runHook postCheck
|
||||
'';
|
||||
|
||||
installPhase = attrs.installPhase or ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out
|
||||
dir="$GOPATH/bin"
|
||||
[ -e "$dir" ] && cp -r $dir $out
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
preFixup = (attrs.preFixup or "") + ''
|
||||
find $out/{bin,libexec,lib} -type f 2>/dev/null | xargs -r ${removeExpr removeReferences} || true
|
||||
'';
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
disallowedReferences = optional (!allowGoReference) go;
|
||||
|
||||
passthru = { inherit go vendorEnv; } // passthru;
|
||||
|
||||
meta = { platforms = go.meta.platforms or platforms.all; } // meta;
|
||||
});
|
||||
|
||||
in
|
||||
{
|
||||
inherit buildGoApplication mkGoEnv;
|
||||
}
|
13
nix/builder/fetch.sh
Normal file
13
nix/builder/fetch.sh
Normal file
|
@ -0,0 +1,13 @@
|
|||
source $stdenv/setup
|
||||
|
||||
export HOME=$(mktemp -d)
|
||||
|
||||
# Call once first outside of subshell for better error reporting
|
||||
go mod download "$goPackagePath@$version"
|
||||
|
||||
dir=$(go mod download --json "$goPackagePath@$version" | jq -r .Dir)
|
||||
|
||||
chmod -R +w $dir
|
||||
find $dir -iname ".ds_store" | xargs -r rm -rf
|
||||
|
||||
cp -r $dir $out
|
57
nix/builder/install/install.go
Normal file
57
nix/builder/install/install.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const filename = "tools.go"
|
||||
|
||||
func main() {
|
||||
fset := token.NewFileSet()
|
||||
|
||||
var src []byte
|
||||
{
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
src, err = io.ReadAll(f)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
f, err := parser.ParseFile(fset, filename, src, parser.ImportsOnly)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, s := range f.Imports {
|
||||
path, err := strconv.Unquote(s.Path.Value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "install", path)
|
||||
|
||||
fmt.Printf("Executing '%s'\n", cmd)
|
||||
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
141
nix/builder/parser.nix
Normal file
141
nix/builder/parser.nix
Normal file
|
@ -0,0 +1,141 @@
|
|||
# Parse go.mod in Nix
|
||||
# Returns a Nix structure with the contents of the go.mod passed in
|
||||
# in normalised form.
|
||||
|
||||
let
|
||||
inherit (builtins) elemAt mapAttrs split foldl' match filter typeOf hasAttr length;
|
||||
|
||||
# Strip lines with comments & other junk
|
||||
stripStr = s: elemAt (split "^ *" (elemAt (split " *$" s) 0)) 2;
|
||||
stripLines = initialLines: foldl' (acc: f: f acc) initialLines [
|
||||
# Strip comments
|
||||
(lines: map
|
||||
(l: stripStr (elemAt (splitString "//" l) 0))
|
||||
lines)
|
||||
|
||||
# Strip leading tabs characters
|
||||
(lines: map (l: elemAt (match "(\t)?(.*)" l) 1) lines)
|
||||
|
||||
# Filter empty lines
|
||||
(filter (l: l != ""))
|
||||
];
|
||||
|
||||
# Parse lines into a structure
|
||||
parseLines = lines: (foldl'
|
||||
(acc: l:
|
||||
let
|
||||
m = match "([^ )]*) *(.*)" l;
|
||||
directive = elemAt m 0;
|
||||
rest = elemAt m 1;
|
||||
|
||||
# Maintain parser state (inside parens or not)
|
||||
inDirective =
|
||||
if rest == "(" then directive
|
||||
else if rest == ")" then null
|
||||
else acc.inDirective
|
||||
;
|
||||
|
||||
in
|
||||
{
|
||||
data = (acc.data // (
|
||||
if directive == "" && rest == ")" then { }
|
||||
else if inDirective != null && rest == "(" && ! hasAttr inDirective acc.data then {
|
||||
${inDirective} = { };
|
||||
}
|
||||
else if rest == "(" || rest == ")" then { }
|
||||
else if inDirective != null then {
|
||||
${inDirective} = acc.data.${inDirective} // { ${directive} = rest; };
|
||||
} else if directive == "replace" then
|
||||
(
|
||||
let
|
||||
segments = split " => " rest;
|
||||
getSegment = elemAt segments;
|
||||
in
|
||||
assert length segments == 3; {
|
||||
replace = acc.data.replace // {
|
||||
${getSegment 0} = "=> ${getSegment 2}";
|
||||
};
|
||||
}
|
||||
)
|
||||
else {
|
||||
${directive} = rest;
|
||||
}
|
||||
)
|
||||
);
|
||||
inherit inDirective;
|
||||
})
|
||||
{
|
||||
inDirective = null;
|
||||
data = {
|
||||
require = { };
|
||||
replace = { };
|
||||
exclude = { };
|
||||
};
|
||||
}
|
||||
lines
|
||||
).data;
|
||||
|
||||
normaliseDirectives = data: (
|
||||
let
|
||||
normaliseString = s:
|
||||
let
|
||||
m = builtins.match "([^ ]+) (.+)" s;
|
||||
in
|
||||
{
|
||||
${elemAt m 0} = elemAt m 1;
|
||||
};
|
||||
require = data.require or { };
|
||||
replace = data.replace or { };
|
||||
exclude = data.exclude or { };
|
||||
in
|
||||
data // {
|
||||
require =
|
||||
if typeOf require == "string" then normaliseString require
|
||||
else require;
|
||||
replace =
|
||||
if typeOf replace == "string" then normaliseString replace
|
||||
else replace;
|
||||
}
|
||||
);
|
||||
|
||||
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 =
|
||||
mapAttrs
|
||||
(_: v:
|
||||
let
|
||||
m = match "=> ([^ ]+) (.+)" v;
|
||||
m2 = match "=> (.*+)" v;
|
||||
in
|
||||
if m != null then {
|
||||
goPackagePath = elemAt m 0;
|
||||
version = elemAt m 1;
|
||||
} else {
|
||||
path = elemAt m2 0;
|
||||
})
|
||||
data.replace;
|
||||
}
|
||||
);
|
||||
|
||||
splitString = sep: s: filter (t: t != [ ]) (split sep s);
|
||||
|
||||
in
|
||||
contents:
|
||||
foldl' (acc: f: f acc) (splitString "\n" contents) [
|
||||
stripLines
|
||||
parseLines
|
||||
normaliseDirectives
|
||||
parseReplace
|
||||
]
|
110
nix/builder/symlink/symlink.go
Normal file
110
nix/builder/symlink/symlink.go
Normal file
|
@ -0,0 +1,110 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type Package struct {
|
||||
GoPackagePath string `json:"-"`
|
||||
Version string `json:"version"`
|
||||
Hash string `json:"hash"`
|
||||
ReplacedPath string `json:"replaced,omitempty"`
|
||||
}
|
||||
|
||||
// type Output struct {
|
||||
// SchemaVersion int `json:"schema"`
|
||||
// Mod map[string]*Package `json:"mod"`
|
||||
// }
|
||||
|
||||
func main() {
|
||||
|
||||
// var output Output
|
||||
sources := make(map[string]string)
|
||||
pkgs := make(map[string]*Package)
|
||||
|
||||
{
|
||||
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]
|
||||
|
||||
paths := []string{key}
|
||||
|
||||
for _, path := range paths {
|
||||
|
||||
vendorDir := filepath.Join("vendor", filepath.Dir(path))
|
||||
if err := os.MkdirAll(vendorDir, 0755); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filepath.Join("vendor", path)); err == nil {
|
||||
files, err := ioutil.ReadDir(src)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, f := range files {
|
||||
innerSrc := filepath.Join(src, f.Name())
|
||||
dst := filepath.Join("vendor", path, f.Name())
|
||||
if err := os.Symlink(innerSrc, dst); err != nil {
|
||||
// assume it's an existing directory, try to link the directory content instead.
|
||||
// TODO should we do this recursively
|
||||
files, err := ioutil.ReadDir(innerSrc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, f := range files {
|
||||
if err := os.Symlink(filepath.Join(innerSrc, f.Name()), filepath.Join(dst, f.Name())); err != nil {
|
||||
fmt.Println("ignore symlink error", filepath.Join(innerSrc, f.Name()), filepath.Join(dst, 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)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue