blob: eb6f75ef30757dc14bfe289fe8afbc331c137a12 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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
]
|