1 # This file originates from composer2nix
3 { stdenv, writeTextFile, fetchurl, php, unzip }:
6 composer = stdenv.mkDerivation {
7 name = "composer-1.8.0";
9 url = https://github.com/composer/composer/releases/download/1.8.0/composer.phar;
10 sha256 = "19pg9ip2mpyf5cyq34fld7qwl77mshqw3c4nif7sxmpnar6sh089";
12 buildInputs = [ php ];
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.
19 mkdir -p $out/share/php
20 cp $src $out/share/php/composer.phar
21 chmod 755 $out/share/php/composer.phar
23 # Create wrapper executable
25 cat > $out/bin/composer <<EOF
27 exec ${php}/bin/php $out/share/php/composer.phar "\$@"
29 chmod +x $out/bin/composer
32 description = "Dependency Manager for PHP";
33 #license = stdenv.licenses.mit;
34 maintainers = [ stdenv.lib.maintainers.sander ];
35 platforms = stdenv.lib.platforms.unix;
39 buildZipPackage = { name, src }:
42 buildInputs = [ unzip ];
45 baseDir=$(find . -type d -mindepth 1 -maxdepth 1)
58 , symlinkDependencies ? false
60 , removeComposerArtifacts ? false
64 , unpackPhase ? "true"
69 reconstructInstalled = writeTextFile {
70 name = "reconstructinstalled.php";
75 if(file_exists($argv[1]))
77 $composerLockStr = file_get_contents($argv[1]);
79 if($composerLockStr === false)
81 fwrite(STDERR, "Cannot open composer.lock contents\n");
86 $config = json_decode($composerLockStr, true);
88 if(array_key_exists("packages", $config))
89 $allPackages = $config["packages"];
91 $allPackages = array();
93 ${stdenv.lib.optionalString (!noDev) ''
94 if(array_key_exists("packages-dev", $config))
95 $allPackages = array_merge($allPackages, $config["packages-dev"]);
98 $packagesStr = json_encode($allPackages, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
108 constructBin = writeTextFile {
109 name = "constructbin.php";
114 $composerJSONStr = file_get_contents($argv[1]);
116 if($composerJSONStr === false)
118 fwrite(STDERR, "Cannot open composer.json contents\n");
123 $config = json_decode($composerJSONStr, true);
125 if(array_key_exists("bin-dir", $config))
126 $binDir = $config["bin-dir"];
130 if(array_key_exists("bin", $config))
132 if(!file_exists("vendor/".$binDir))
133 mkdir("vendor/".$binDir);
135 foreach($config["bin"] as $bin)
136 symlink("../../".$bin, "vendor/".$binDir."/".basename($bin));
143 bundleDependencies = dependencies:
144 stdenv.lib.concatMapStrings (dependencyName:
146 dependency = dependencies.${dependencyName};
149 ${if dependency.targetDir == "" then ''
150 vendorDir="$(dirname ${dependencyName})"
151 mkdir -p "$vendorDir"
152 ${if symlinkDependencies then
153 ''ln -s "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
155 ''cp -av "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
156 }${if dependency.needsModifyRights or false then "\n" + ''
157 chmod -R u+rwx "$vendorDir/$(basename "${dependencyName}")"
160 namespaceDir="${dependencyName}/$(dirname "${dependency.targetDir}")"
161 mkdir -p "$namespaceDir"
162 ${if symlinkDependencies then
163 ''ln -s "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
165 ''cp -av "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
166 }${if dependency.needsModifyRights or false then "\n" + ''
167 chmod -R u+rwx "$namespaceDir/$(basename "${dependency.targetDir}")"
170 '') (builtins.attrNames dependencies);
172 extraArgs = removeAttrs args [ "name" "packages" "devPackages" "buildInputs" ];
174 stdenv.mkDerivation ({
175 name = "composer-${name}";
176 buildInputs = [ php composer ] ++ buildInputs;
178 inherit unpackPhase buildPhase;
181 ${if executable then ''
182 mkdir -p $out/share/php
183 cp -av $src $out/share/php/$name
184 chmod -R u+w $out/share/php/$name
185 cd $out/share/php/$name
192 # Execute pre install hook
195 # Remove unwanted files
200 # Remove the provided vendor folder if it exists
203 # If there is no composer.lock file, compose a dummy file.
204 # Otherwise, composer attempts to download the package.json file from
205 # the registry which we do not want.
206 if [ ! -f composer.lock ]
208 cat > composer.lock <<EOF
215 # Reconstruct the installed.json file from the lock file
216 mkdir -p vendor/composer
217 ${reconstructInstalled} composer.lock > vendor/composer/installed.json
219 # Copy or symlink the provided dependencies
221 ${bundleDependencies packages}
222 ${stdenv.lib.optionalString (!noDev) (bundleDependencies devPackages)}
225 # Reconstruct autoload scripts
226 # We use the optimize feature because Nix packages cannot change after they have been built
227 # Using the dynamic loader for a Nix package is useless since there is nothing to dynamically reload.
228 composer dump-autoload --optimize ${stdenv.lib.optionalString noDev "--no-dev"}
230 # Run the install step as a validation to confirm that everything works out as expected
231 composer install --optimize-autoloader ${stdenv.lib.optionalString noDev "--no-dev"}
233 ${stdenv.lib.optionalString executable ''
234 # Reconstruct the bin/ folder if we deploy an executable project
235 ${constructBin} composer.json
236 ln -s $(pwd)/vendor/bin $out/bin
239 ${stdenv.lib.optionalString (!symlinkDependencies) ''
240 # Patch the shebangs if possible
241 if [ -d $(pwd)/vendor/bin ]
243 # Look for all executables in bin/
244 for i in $(pwd)/vendor/bin/*
246 # Look for their location
247 realFile=$(readlink -f "$i")
249 # Restore write permissions
250 chmod u+wx "$(dirname "$realFile")"
251 chmod u+w "$realFile"
254 sed -e "s|#!/usr/bin/php|#!${php}/bin/php|" \
255 -e "s|#!/usr/bin/env php|#!${php}/bin/php|" \
258 chmod u+x "$realFile"
263 if [ "$removeComposerArtifacts" = "1" ]
265 # Remove composer stuff
266 rm -f composer.json composer.lock
269 # Execute post install hook
275 composer = stdenv.lib.makeOverridable composer;
276 buildZipPackage = stdenv.lib.makeOverridable buildZipPackage;
277 buildPackage = stdenv.lib.makeOverridable buildPackage;