forked from CrazyChaoz/gradle-dot-nix
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdefault.nix
235 lines (226 loc) · 11.1 KB
/
default.nix
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
{ pkgs,
gradle-verification-metadata-file,
public-maven-repos ? ''
[
"https://dl.google.com/dl/android/maven2",
"https://repo.maven.apache.org/maven2",
"https://plugins.gradle.org/m2",
"https://maven.google.com"
]
'',
local-maven-repos ? [ ]
}:
let
impureEnvVars = pkgs.lib.fetchers.proxyImpureEnvVars ++ [ "NETRC" "netrc" ];
local-repos-string = pkgs.lib.concatStringsSep " " local-maven-repos;
# we need to convert the gradle metadata to json
# this json data is completely static and can be used to fetch the dependencies
gradle-deps-json = pkgs.stdenv.mkDerivation {
name = "gradle-deps-json";
src = ./.;
buildInputs = [ pkgs.python3 ];
buildPhase = ''
python3 gradle-metadata-to-json.py ${gradle-verification-metadata-file} $out
'';
};
# we need to convert the json data to data that nix understands
gradle-deps-nix = builtins.fromJSON (builtins.readFile gradle-deps-json);
public-maven-repos-file = pkgs.writeText "public-maven-repos.json" public-maven-repos;
# the central conversion function
# it takes one dependency description (a nix attribute set) and converts it to a nix derivation
# depending on the type of the dependency, we need to do different things
#
# if we set the is_added_pom_file attribute to true, we can just create a file with the pom content
# this is done, because sometimes there are dependencies which are missing their pom file in the metadata file, but gradle complains if they're missing
# taken from: https://gist.github.com/tadfisher/17000caf8653019a9a98fd9b9b921d93#file-maven-repo-nix
#
# if we set the has_module_file attribute to true, we need to fetch the module file and rename it to the artifact name
# this is done because sometimes ther is renaming happening in the module file, which is not reflected in the metadata file
# the file in verification-metadata.xml has a different name than the file on the server
# so we need to fetch the module file, get the mapping of names and fetch the correct file
# for the name in the store we need the name from the module information again, so we need the derivation for the module again.
# this can probably be optimized, but for now it's fine
#
# the third case is where we just fetch the file from the server
# this is only done for .module files, because they are never renamed
conversion-function = unique-dependency:
if unique-dependency.is_added_pom_file == "true" then
let
actual-file = pkgs.writeText unique-dependency.artifact_name ''
<project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- This module was also published with a richer model, Gradle metadata, -->
<!-- which should be used instead. Do not delete the following line which -->
<!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
<!-- that they should prefer consuming it instead. -->
<!-- do_not_remove: published-with-gradle-metadata -->
<modelVersion>4.0.0</modelVersion>
<groupId>${unique-dependency.group}</groupId>
<artifactId>${unique-dependency.name}</artifactId>
<version>${unique-dependency.version}</version>
</project>
'';
in
pkgs.stdenv.mkDerivation {
name = unique-dependency.artifact_name;
src = ./.;
inherit impureEnvVars;
INTERNAL_PATH = unique-dependency.artifact_dir + "/" + unique-dependency.artifact_name;
installPhase = ''
directory=$out/$(dirname "$INTERNAL_PATH")
mkdir -p $directory
cp ${actual-file} $out/$INTERNAL_PATH
'';
}
else if unique-dependency.has_module_file == "true" then
let
module-derivation = pkgs.stdenv.mkDerivation {
name = unique-dependency.module_file.artifact_name;
src = ./.;
nativeBuildInputs = [ pkgs.python3 pkgs.python3Packages.requests ];
inherit impureEnvVars;
installPhase = ''
local=$(find ${local-repos-string} -name '${unique-dependency.artifact_name}' -type f -print -quit)
if [[ $local ]]; then
cp $local $out
else
python3 fetch-gradle-dependency.py $out fetch-module ${public-maven-repos-file} ${unique-dependency.module_file.name} ${unique-dependency.module_file.group} ${unique-dependency.module_file.version} ${unique-dependency.module_file.artifact_name} ${unique-dependency.module_file.artifact_dir} ${unique-dependency.module_file.sha_256}
fi
'';
outputHashAlgo = "sha256";
outputHash = unique-dependency.module_file.sha_256;
};
actual-file = pkgs.stdenv.mkDerivation {
name = unique-dependency.artifact_name;
src = ./.;
nativeBuildInputs = [ pkgs.python3 pkgs.python3Packages.requests ];
inherit impureEnvVars;
installPhase = ''
local=$(find ${local-repos-string} -name '${unique-dependency.artifact_name}' -type f -print -quit)
if [[ $local ]]; then
cp $local $out
else
python3 fetch-gradle-dependency.py $out fetch-file ${public-maven-repos-file} ${unique-dependency.name} ${unique-dependency.group} ${unique-dependency.version} ${unique-dependency.artifact_name} ${unique-dependency.artifact_dir} ${unique-dependency.sha_256} ${unique-dependency.module_file.artifact_name}
fi
'';
outputHashAlgo = "sha256";
outputHash = unique-dependency.sha_256;
};
in
pkgs.stdenv.mkDerivation {
name = unique-dependency.artifact_name;
src = ./.;
nativeBuildInputs = [ pkgs.python3 ];
inherit impureEnvVars;
installPhase = ''
INTERNAL_PATH=`python3 rename-module.py ${module-derivation} ${unique-dependency.artifact_name} ${unique-dependency.artifact_dir}`
directory=$out/$(dirname "$INTERNAL_PATH")
mkdir -p $directory
cp ${actual-file} $out/$INTERNAL_PATH
'';
}
else
let
actual-file = pkgs.stdenv.mkDerivation {
name = unique-dependency.artifact_name;
src = ./.;
nativeBuildInputs = [ pkgs.python3 pkgs.python3Packages.requests ];
inherit impureEnvVars;
installPhase = ''
local=$(find ${local-repos-string} -name '${unique-dependency.artifact_name}' -type f -print -quit)
if [[ $local ]]; then
cp $local $out
else
python3 fetch-gradle-dependency.py $out fetch-module ${public-maven-repos-file} ${unique-dependency.name} ${unique-dependency.group} ${unique-dependency.version} ${unique-dependency.artifact_name} ${unique-dependency.artifact_dir} ${unique-dependency.sha_256}
fi
'';
outputHashAlgo = "sha256";
outputHash = unique-dependency.sha_256;
};
in
pkgs.stdenv.mkDerivation {
name = unique-dependency.artifact_name;
src = ./.;
INTERNAL_PATH = unique-dependency.artifact_dir + "/" + unique-dependency.artifact_name;
inherit impureEnvVars;
installPhase = ''
directory=$out/$(dirname "$INTERNAL_PATH")
mkdir -p $directory
cp ${actual-file} $out/$INTERNAL_PATH
'';
fixupPhase = ''
echo "no need fixing up $out"
'';
}
;
# this is where all the dependencies are collected into a single repository
# the pkgs.linkFarm function takes an array of attribute sets
# --> each with
# --> * name: is converted to a path in the output
# --> * path: the actual path to the derivation
# the output of this function is a single derivation which contains all the dependencies
# the input is the array of the nixified dependencies, which are fed into the conversion function
gradle-dependency-maven-repo = pkgs.symlinkJoin { name = "maven-repo"; paths = (map conversion-function gradle-deps-nix.components); postBuild = "echo maven repository was built"; };
# idea taken from https://bmcgee.ie/posts/2023/02/nix-what-are-fixed-output-derivations-and-why-use-them/
# gradle has a huge disliking for self fetched dependencies
# it usually tries to fetch the dependencies itself, which is not what we want
# we want to use an offline repository, so we need to tell gradle to use our repository
# there are 3 ways to use offline dependencies in gradle
# 1. use the cached dependencies from the gradle cache under ~/.gradle/caches/modules-2/files-2.1
# --> this would be perfect, but gradle does not like to use the cache if its own metadata files are not present, and those are nondeterministic
# --> could still be valid, since no nondeterminism escapes the sandbox, it probably just stems from some internal cache invalidation strategy
# 2. we can create a maven repo that we reference in the build configuration
# --> this was state-of-the-art when dealing with offline dependencies, but it's not the best solution anymore (i think)
# --> this is what also can be done with ${gradle-dependency-maven-repo}
# 3. we can use the init.gradle file to tell gradle to use our repository
# --> this is the best solution, because it's the most flexible and the most explicit
# --> we can use the init.gradle file to tell gradle to use our repository
# --> there can even be multiple init.gradle files, so there is not even a need to avoid other init files, we can just add our own
# --> and this does not / should not require any changes to the build configuration
# --> it is a transparent change
#
# what is happening here?
# we create a file called init.gradle.kts
# it changes the project settings (settings.gradle.kts or settings.gradle) to use our repository
# i'm not sure if we also need repositoriesMode.set(RepositoriesMode.PREFER_PROJECT), but it surely helps
gradleInit = pkgs.writeText "init.gradle.kts" ''
beforeSettings {
System.setProperty(
"org.gradle.internal.plugins.portal.url.override",
"${gradle-dependency-maven-repo}"
)
}
projectsLoaded {
rootProject.allprojects {
buildscript {
repositories {
maven { url = uri("${gradle-dependency-maven-repo}") }
}
}
repositories {
maven { url = uri("${gradle-dependency-maven-repo}") }
}
}
}
settingsEvaluated {
pluginManagement {
repositories {
maven { url = uri("${gradle-dependency-maven-repo}") }
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
repositories {
maven { url = uri("${gradle-dependency-maven-repo}") }
}
}
}
'';
in
{
mvn-repo = gradle-dependency-maven-repo;
gradle-init = gradleInit;
gradle-deps-json = gradle-deps-json;
}