Merge pull request #8 from tweag/local-vendor
Add support for local replace directives
This commit is contained in:
commit
c78d7b9f15
2 changed files with 156 additions and 0 deletions
|
@ -8,11 +8,14 @@
|
|||
}:
|
||||
let
|
||||
|
||||
parseGoMod = import ./parser.nix;
|
||||
|
||||
removeExpr = refs: ''remove-references-to ${lib.concatMapStrings (ref: " -t ${ref}") refs}'';
|
||||
|
||||
buildGoApplication =
|
||||
{ modules
|
||||
, src
|
||||
, pwd ? null
|
||||
, CGO_ENABLED ? "0"
|
||||
, nativeBuildInputs ? [ ]
|
||||
, allowGoReference ? false
|
||||
|
@ -23,6 +26,22 @@ let
|
|||
let
|
||||
modulesStruct = builtins.fromTOML (builtins.readFile modules);
|
||||
|
||||
goMod = parseGoMod (builtins.readFile "${builtins.toString pwd}/go.mod");
|
||||
localReplaceCommands =
|
||||
let
|
||||
localReplaceAttrs = lib.filterAttrs (n: v: lib.hasAttr "path" v) goMod.replace;
|
||||
commands = (
|
||||
lib.mapAttrsToList
|
||||
(name: value: (
|
||||
''
|
||||
mkdir -p $(dirname vendor/${name})
|
||||
ln -s ${pwd + "/${value.path}"} vendor/${name}
|
||||
''
|
||||
))
|
||||
localReplaceAttrs);
|
||||
in
|
||||
if pwd != null then commands else [ ];
|
||||
|
||||
vendorEnv = runCommand "vendor-env"
|
||||
{
|
||||
nativeBuildInputs = [ go ];
|
||||
|
@ -50,6 +69,9 @@ let
|
|||
export GOPATH="$TMPDIR/go"
|
||||
|
||||
go run ${./symlink.go}
|
||||
${lib.concatStringsSep "\n" localReplaceCommands}
|
||||
|
||||
find vendor
|
||||
|
||||
mv vendor $out
|
||||
''
|
||||
|
|
134
builder/parser.nix
Normal file
134
builder/parser.nix
Normal file
|
@ -0,0 +1,134 @@
|
|||
# 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;
|
||||
|
||||
# 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:
|
||||
let
|
||||
m = match "(.*)( |)//.*" l;
|
||||
hasComment = m != null;
|
||||
in
|
||||
stripStr (if hasComment then elemAt m 0 else l))
|
||||
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 == "(" then {
|
||||
${inDirective} = { };
|
||||
} else if inDirective != null then {
|
||||
${inDirective} = acc.data.${inDirective} // { ${directive} = rest; };
|
||||
} else {
|
||||
${directive} = rest;
|
||||
}
|
||||
);
|
||||
inherit inDirective;
|
||||
})
|
||||
{
|
||||
inDirective = null;
|
||||
data = { };
|
||||
}
|
||||
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
|
||||
(n: v:
|
||||
let
|
||||
m = match "=> (.+?) (.+)" v;
|
||||
m2 = match "=> (.*+)" v;
|
||||
in
|
||||
if m != null then {
|
||||
goPackagePath = elemAt m 0;
|
||||
version = parseVersion (elemAt m 1);
|
||||
} else {
|
||||
path = elemAt m2 0;
|
||||
})
|
||||
data.replace;
|
||||
}
|
||||
);
|
||||
|
||||
parseRequire = data: (
|
||||
data // {
|
||||
require = mapAttrs (n: v: parseVersion v) data.require;
|
||||
}
|
||||
);
|
||||
|
||||
splitString = sep: s: filter (t: t != [ ]) (split sep s);
|
||||
|
||||
in
|
||||
contents:
|
||||
foldl' (acc: f: f acc) (splitString "\n" contents) [
|
||||
stripLines
|
||||
parseLines
|
||||
normaliseDirectives
|
||||
parseReplace
|
||||
parseRequire
|
||||
]
|
Loading…
Reference in a new issue