diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-12-13 21:25:24 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2019-05-24 01:40:13 +0200 |
commit | 24fd1fe6c62b7a9fc347794fde043285da272f5c (patch) | |
tree | 65557bf1d241ca389b619dbd24d18d51932ee030 /pkgs/composer-env/default.nix | |
download | NUR-24fd1fe6c62b7a9fc347794fde043285da272f5c.tar.gz NUR-24fd1fe6c62b7a9fc347794fde043285da272f5c.tar.zst NUR-24fd1fe6c62b7a9fc347794fde043285da272f5c.zip |
Initial commit published for NUR
Diffstat (limited to 'pkgs/composer-env/default.nix')
-rw-r--r-- | pkgs/composer-env/default.nix | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/pkgs/composer-env/default.nix b/pkgs/composer-env/default.nix new file mode 100644 index 00000000..416a61ca --- /dev/null +++ b/pkgs/composer-env/default.nix | |||
@@ -0,0 +1,280 @@ | |||
1 | # This file originates from composer2nix | ||
2 | |||
3 | { stdenv, writeTextFile, fetchurl, php, unzip }: | ||
4 | |||
5 | let | ||
6 | composer = stdenv.mkDerivation { | ||
7 | name = "composer-1.8.0"; | ||
8 | src = fetchurl { | ||
9 | url = https://github.com/composer/composer/releases/download/1.8.0/composer.phar; | ||
10 | sha256 = "19pg9ip2mpyf5cyq34fld7qwl77mshqw3c4nif7sxmpnar6sh089"; | ||
11 | }; | ||
12 | buildInputs = [ php ]; | ||
13 | |||
14 | # We must wrap the composer.phar because of the impure shebang. | ||
15 | # We cannot use patchShebangs because the executable verifies its own integrity and will detect that somebody has tampered with it. | ||
16 | |||
17 | buildCommand = '' | ||
18 | # Copy phar file | ||
19 | mkdir -p $out/share/php | ||
20 | cp $src $out/share/php/composer.phar | ||
21 | chmod 755 $out/share/php/composer.phar | ||
22 | |||
23 | # Create wrapper executable | ||
24 | mkdir -p $out/bin | ||
25 | cat > $out/bin/composer <<EOF | ||
26 | #! ${stdenv.shell} -e | ||
27 | exec ${php}/bin/php $out/share/php/composer.phar "\$@" | ||
28 | EOF | ||
29 | chmod +x $out/bin/composer | ||
30 | ''; | ||
31 | meta = { | ||
32 | description = "Dependency Manager for PHP"; | ||
33 | #license = stdenv.licenses.mit; | ||
34 | maintainers = [ stdenv.lib.maintainers.sander ]; | ||
35 | platforms = stdenv.lib.platforms.unix; | ||
36 | }; | ||
37 | }; | ||
38 | |||
39 | buildZipPackage = { name, src }: | ||
40 | stdenv.mkDerivation { | ||
41 | inherit name src; | ||
42 | buildInputs = [ unzip ]; | ||
43 | buildCommand = '' | ||
44 | unzip $src | ||
45 | baseDir=$(find . -type d -mindepth 1 -maxdepth 1) | ||
46 | cd $baseDir | ||
47 | mkdir -p $out | ||
48 | mv * $out | ||
49 | ''; | ||
50 | }; | ||
51 | |||
52 | buildPackage = | ||
53 | { name | ||
54 | , src | ||
55 | , packages ? {} | ||
56 | , devPackages ? {} | ||
57 | , buildInputs ? [] | ||
58 | , symlinkDependencies ? false | ||
59 | , executable ? false | ||
60 | , removeComposerArtifacts ? false | ||
61 | , postInstall ? "" | ||
62 | , preInstall ? "" | ||
63 | , noDev ? false | ||
64 | , unpackPhase ? "true" | ||
65 | , buildPhase ? "true" | ||
66 | , doRemoveVendor ? true | ||
67 | , ...}@args: | ||
68 | |||
69 | let | ||
70 | reconstructInstalled = writeTextFile { | ||
71 | name = "reconstructinstalled.php"; | ||
72 | executable = true; | ||
73 | text = '' | ||
74 | #! ${php}/bin/php | ||
75 | <?php | ||
76 | if(file_exists($argv[1])) | ||
77 | { | ||
78 | $composerLockStr = file_get_contents($argv[1]); | ||
79 | |||
80 | if($composerLockStr === false) | ||
81 | { | ||
82 | fwrite(STDERR, "Cannot open composer.lock contents\n"); | ||
83 | exit(1); | ||
84 | } | ||
85 | else | ||
86 | { | ||
87 | $config = json_decode($composerLockStr, true); | ||
88 | |||
89 | if(array_key_exists("packages", $config)) | ||
90 | $allPackages = $config["packages"]; | ||
91 | else | ||
92 | $allPackages = array(); | ||
93 | |||
94 | ${stdenv.lib.optionalString (!noDev) '' | ||
95 | if(array_key_exists("packages-dev", $config)) | ||
96 | $allPackages = array_merge($allPackages, $config["packages-dev"]); | ||
97 | ''} | ||
98 | |||
99 | $packagesStr = json_encode($allPackages, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); | ||
100 | print($packagesStr); | ||
101 | } | ||
102 | } | ||
103 | else | ||
104 | print("[]"); | ||
105 | ?> | ||
106 | ''; | ||
107 | }; | ||
108 | |||
109 | constructBin = writeTextFile { | ||
110 | name = "constructbin.php"; | ||
111 | executable = true; | ||
112 | text = '' | ||
113 | #! ${php}/bin/php | ||
114 | <?php | ||
115 | $composerJSONStr = file_get_contents($argv[1]); | ||
116 | |||
117 | if($composerJSONStr === false) | ||
118 | { | ||
119 | fwrite(STDERR, "Cannot open composer.json contents\n"); | ||
120 | exit(1); | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | $config = json_decode($composerJSONStr, true); | ||
125 | |||
126 | if(array_key_exists("bin-dir", $config)) | ||
127 | $binDir = $config["bin-dir"]; | ||
128 | else | ||
129 | $binDir = "bin"; | ||
130 | |||
131 | if(array_key_exists("bin", $config)) | ||
132 | { | ||
133 | if(!file_exists("vendor/".$binDir)) | ||
134 | mkdir("vendor/".$binDir); | ||
135 | |||
136 | foreach($config["bin"] as $bin) | ||
137 | symlink("../../".$bin, "vendor/".$binDir."/".basename($bin)); | ||
138 | } | ||
139 | } | ||
140 | ?> | ||
141 | ''; | ||
142 | }; | ||
143 | |||
144 | bundleDependencies = dependencies: | ||
145 | stdenv.lib.concatMapStrings (dependencyName: | ||
146 | let | ||
147 | dependency = dependencies.${dependencyName}; | ||
148 | in | ||
149 | '' | ||
150 | ${if dependency.targetDir == "" then '' | ||
151 | vendorDir="$(dirname ${dependencyName})" | ||
152 | mkdir -p "$vendorDir" | ||
153 | ${if symlinkDependencies then | ||
154 | ''ln -s "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"'' | ||
155 | else | ||
156 | ''cp -a "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"'' | ||
157 | }${if dependency.needsModifyRights or false then "\n" + '' | ||
158 | chmod -R u+rwx "$vendorDir/$(basename "${dependencyName}")" | ||
159 | '' else ""} | ||
160 | '' else '' | ||
161 | namespaceDir="${dependencyName}/$(dirname "${dependency.targetDir}")" | ||
162 | mkdir -p "$namespaceDir" | ||
163 | ${if symlinkDependencies then | ||
164 | ''ln -s "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"'' | ||
165 | else | ||
166 | ''cp -a "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"'' | ||
167 | }${if dependency.needsModifyRights or false then "\n" + '' | ||
168 | chmod -R u+rwx "$namespaceDir/$(basename "${dependency.targetDir}")" | ||
169 | '' else ""} | ||
170 | ''} | ||
171 | '') (builtins.attrNames dependencies); | ||
172 | |||
173 | extraArgs = removeAttrs args [ "name" "packages" "devPackages" "buildInputs" ]; | ||
174 | in | ||
175 | stdenv.mkDerivation ({ | ||
176 | name = "composer-${name}"; | ||
177 | buildInputs = [ php composer ] ++ buildInputs; | ||
178 | |||
179 | inherit unpackPhase buildPhase; | ||
180 | |||
181 | installPhase = '' | ||
182 | ${if executable then '' | ||
183 | mkdir -p $out/share/php | ||
184 | cp -a $src $out/share/php/$name | ||
185 | chmod -R u+w $out/share/php/$name | ||
186 | cd $out/share/php/$name | ||
187 | '' else '' | ||
188 | cp -a $src $out | ||
189 | chmod -R u+w $out | ||
190 | cd $out | ||
191 | ''} | ||
192 | |||
193 | # Execute pre install hook | ||
194 | runHook preInstall | ||
195 | |||
196 | # Remove unwanted files | ||
197 | rm -f *.nix | ||
198 | |||
199 | export HOME=$TMPDIR | ||
200 | |||
201 | ${if doRemoveVendor then '' | ||
202 | # Remove the provided vendor folder if it exists | ||
203 | rm -Rf vendor | ||
204 | '' else ""} | ||
205 | # If there is no composer.lock file, compose a dummy file. | ||
206 | # Otherwise, composer attempts to download the package.json file from | ||
207 | # the registry which we do not want. | ||
208 | if [ ! -f composer.lock ] | ||
209 | then | ||
210 | cat > composer.lock <<EOF | ||
211 | { | ||
212 | "packages": [] | ||
213 | } | ||
214 | EOF | ||
215 | fi | ||
216 | |||
217 | # Reconstruct the installed.json file from the lock file | ||
218 | mkdir -p vendor/composer | ||
219 | ${reconstructInstalled} composer.lock > vendor/composer/installed.json | ||
220 | |||
221 | # Copy or symlink the provided dependencies | ||
222 | cd vendor | ||
223 | ${bundleDependencies packages} | ||
224 | ${stdenv.lib.optionalString (!noDev) (bundleDependencies devPackages)} | ||
225 | cd .. | ||
226 | |||
227 | # Reconstruct autoload scripts | ||
228 | # We use the optimize feature because Nix packages cannot change after they have been built | ||
229 | # Using the dynamic loader for a Nix package is useless since there is nothing to dynamically reload. | ||
230 | composer dump-autoload --optimize ${stdenv.lib.optionalString noDev "--no-dev"} | ||
231 | |||
232 | # Run the install step as a validation to confirm that everything works out as expected | ||
233 | composer install --optimize-autoloader ${stdenv.lib.optionalString noDev "--no-dev"} | ||
234 | |||
235 | ${stdenv.lib.optionalString executable '' | ||
236 | # Reconstruct the bin/ folder if we deploy an executable project | ||
237 | ${constructBin} composer.json | ||
238 | ln -s $(pwd)/vendor/bin $out/bin | ||
239 | ''} | ||
240 | |||
241 | ${stdenv.lib.optionalString (!symlinkDependencies) '' | ||
242 | # Patch the shebangs if possible | ||
243 | if [ -d $(pwd)/vendor/bin ] | ||
244 | then | ||
245 | # Look for all executables in bin/ | ||
246 | for i in $(pwd)/vendor/bin/* | ||
247 | do | ||
248 | # Look for their location | ||
249 | realFile=$(readlink -f "$i") | ||
250 | |||
251 | # Restore write permissions | ||
252 | chmod u+wx "$(dirname "$realFile")" | ||
253 | chmod u+w "$realFile" | ||
254 | |||
255 | # Patch shebang | ||
256 | sed -e "s|#!/usr/bin/php|#!${php}/bin/php|" \ | ||
257 | -e "s|#!/usr/bin/env php|#!${php}/bin/php|" \ | ||
258 | "$realFile" > tmp | ||
259 | mv tmp "$realFile" | ||
260 | chmod u+x "$realFile" | ||
261 | done | ||
262 | fi | ||
263 | ''} | ||
264 | |||
265 | if [ "$removeComposerArtifacts" = "1" ] | ||
266 | then | ||
267 | # Remove composer stuff | ||
268 | rm -f composer.json composer.lock | ||
269 | fi | ||
270 | |||
271 | # Execute post install hook | ||
272 | runHook postInstall | ||
273 | ''; | ||
274 | } // extraArgs); | ||
275 | in | ||
276 | { | ||
277 | composer = stdenv.lib.makeOverridable composer; | ||
278 | buildZipPackage = stdenv.lib.makeOverridable buildZipPackage; | ||
279 | buildPackage = stdenv.lib.makeOverridable buildPackage; | ||
280 | } | ||