Merge pull request #90 from nix-community/gomod-parser-comments

Litter go.mod parser with comments
This commit is contained in:
adisbladis 2022-09-02 17:06:18 +12:00 committed by GitHub
commit b5bb2405a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -24,9 +24,9 @@ let
parseLines = lines: (foldl' parseLines = lines: (foldl'
(acc: l: (acc: l:
let let
m = match "([^ )]*) *(.*)" l; m = match "([^ )]*) *(.*)" l; # Match the current line
directive = elemAt m 0; directive = elemAt m 0; # The directive (replace, require & so on)
rest = elemAt m 1; rest = elemAt m 1; # The rest of the current line
# Maintain parser state (inside parens or not) # Maintain parser state (inside parens or not)
inDirective = inDirective =
@ -38,25 +38,40 @@ let
in in
{ {
data = (acc.data // ( data = (acc.data // (
# If a we're in a directive and it's closing, no-op
if directive == "" && rest == ")" then { } if directive == "" && rest == ")" then { }
# If a directive is opening create the directive attrset
else if inDirective != null && rest == "(" && ! hasAttr inDirective acc.data then { else if inDirective != null && rest == "(" && ! hasAttr inDirective acc.data then {
${inDirective} = { }; ${inDirective} = { };
} }
# If we're closing any paren, no-op
else if rest == "(" || rest == ")" then { } else if rest == "(" || rest == ")" then { }
# If we're in a directive that has rest data assign it to the directive in the output
else if inDirective != null then { else if inDirective != null then {
${inDirective} = acc.data.${inDirective} // { ${directive} = rest; }; ${inDirective} = acc.data.${inDirective} // { ${directive} = rest; };
} else if directive == "replace" then }
# Replace directive has unique structure and needs special casing
else if directive == "replace" then
( (
let let
# Split `foo => bar` into segments
segments = split " => " rest; segments = split " => " rest;
getSegment = elemAt segments; getSegment = elemAt segments;
in in
assert length segments == 3; { assert length segments == 3; {
# Assert well formed
replace = acc.data.replace // { replace = acc.data.replace // {
# Structure segments into attrset
${getSegment 0} = "=> ${getSegment 2}"; ${getSegment 0} = "=> ${getSegment 2}";
}; };
} }
) )
# The default operation is to just assign the value
else { else {
${directive} = rest; ${directive} = rest;
} }
@ -65,7 +80,9 @@ let
inherit inDirective; inherit inDirective;
}) })
{ {
# Default foldl' state
inDirective = null; inDirective = null;
# The actual return data we're interested in (default empty structure)
data = { data = {
require = { }; require = { };
replace = { }; replace = { };
@ -75,6 +92,19 @@ let
lines lines
).data; ).data;
# Normalise directives no matter what syntax produced them
# meaning that:
# replace github.com/nix-community/trustix/packages/go-lib => ../go-lib
#
# and:
# replace (
# github.com/nix-community/trustix/packages/go-lib => ../go-lib
# )
#
# gets the same structural representation.
#
# Addtionally this will create directives that are entirely missing from go.mod
# as an empty attrset so it's output is more consistent.
normaliseDirectives = data: ( normaliseDirectives = data: (
let let
normaliseString = s: normaliseString = s:
@ -98,6 +128,7 @@ let
} }
); );
# Parse versions and dates from go.mod version string
parseVersion = ver: parseVersion = ver:
let let
m = elemAt (match "([^-]+)-?([^-]*)-?([^-]*)" ver); m = elemAt (match "([^-]+)-?([^-]*)-?([^-]*)" ver);
@ -110,6 +141,7 @@ let
rev = m 2; rev = m 2;
}; };
# Parse package paths & versions from replace directives
parseReplace = data: ( parseReplace = data: (
data // { data // {
replace = replace =