1 # This file originates from composer2nix
3 { stdenv, lib, writeTextFile, fetchurl, php, unzip, phpPackages }:
6 inherit (phpPackages) composer;
9 builtins.filterSource (path: type: type != "directory" || (baseNameOf path != ".git" && baseNameOf path != ".git" && baseNameOf path != ".svn")) src;
11 buildZipPackage = { name, src }:
14 nativeBuildInputs = [ unzip ];
18 baseDir=$(find . -type d -mindepth 1 -maxdepth 1)
31 , symlinkDependencies ? false
33 , removeComposerArtifacts ? false
36 , composerExtraArgs ? ""
37 , unpackPhase ? "true"
42 reconstructInstalled = writeTextFile {
43 name = "reconstructinstalled.php";
48 if(file_exists($argv[1]))
50 $composerLockStr = file_get_contents($argv[1]);
52 if($composerLockStr === false)
54 fwrite(STDERR, "Cannot open composer.lock contents\n");
59 $config = json_decode($composerLockStr, true);
61 if(array_key_exists("packages", $config))
62 $allPackages = $config["packages"];
64 $allPackages = array();
66 ${lib.optionalString (!noDev) ''
67 if(array_key_exists("packages-dev", $config))
68 $allPackages = array_merge($allPackages, $config["packages-dev"]);
71 $packagesStr = json_encode($allPackages, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
81 constructBin = writeTextFile {
82 name = "constructbin.php";
87 $composerJSONStr = file_get_contents($argv[1]);
89 if($composerJSONStr === false)
91 fwrite(STDERR, "Cannot open composer.json contents\n");
96 $config = json_decode($composerJSONStr, true);
98 if(array_key_exists("bin-dir", $config))
99 $binDir = $config["bin-dir"];
103 if(array_key_exists("bin", $config))
105 if(!file_exists("vendor/".$binDir))
106 mkdir("vendor/".$binDir);
108 foreach($config["bin"] as $bin)
109 symlink("../../".$bin, "vendor/".$binDir."/".basename($bin));
116 bundleDependencies = dependencies:
117 lib.concatMapStrings (dependencyName:
119 dependency = dependencies.${dependencyName};
122 ${if dependency.targetDir == "" then ''
123 vendorDir="$(dirname ${dependencyName})"
124 mkdir -p "$vendorDir"
125 ${if symlinkDependencies then
126 ''ln -s "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
128 ''cp -av "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
131 namespaceDir="${dependencyName}/$(dirname "${dependency.targetDir}")"
132 mkdir -p "$namespaceDir"
133 ${if symlinkDependencies then
134 ''ln -s "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
136 ''cp -av "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
139 '') (builtins.attrNames dependencies);
141 extraArgs = removeAttrs args [ "packages" "devPackages" "buildInputs" ];
143 stdenv.mkDerivation ({
144 buildInputs = [ php composer ] ++ buildInputs;
146 inherit unpackPhase buildPhase;
149 ${if executable then ''
150 mkdir -p $out/share/php
151 cp -av $src $out/share/php/$name
152 chmod -R u+w $out/share/php/$name
153 cd $out/share/php/$name
160 # Remove unwanted files
165 # Remove the provided vendor folder if it exists
168 # If there is no composer.lock file, compose a dummy file.
169 # Otherwise, composer attempts to download the package.json file from
170 # the registry which we do not want.
171 if [ ! -f composer.lock ]
173 cat > composer.lock <<EOF
180 # Reconstruct the installed.json file from the lock file
181 mkdir -p vendor/composer
182 ${php}/bin/php ${reconstructInstalled} composer.lock > vendor/composer/installed.json
184 # Copy or symlink the provided dependencies
186 ${bundleDependencies packages}
187 ${lib.optionalString (!noDev) (bundleDependencies devPackages)}
190 # Reconstruct autoload scripts
191 # We use the optimize feature because Nix packages cannot change after they have been built
192 # Using the dynamic loader for a Nix package is useless since there is nothing to dynamically reload.
193 composer dump-autoload --optimize ${lib.optionalString noDev "--no-dev"} ${composerExtraArgs}
195 # Run the install step as a validation to confirm that everything works out as expected
196 composer install --optimize-autoloader ${lib.optionalString noDev "--no-dev"} ${composerExtraArgs}
198 ${lib.optionalString executable ''
199 # Reconstruct the bin/ folder if we deploy an executable project
200 ${php}/bin/php ${constructBin} composer.json
201 ln -s $(pwd)/vendor/bin $out/bin
204 ${lib.optionalString (!symlinkDependencies) ''
205 # Patch the shebangs if possible
206 if [ -d $(pwd)/vendor/bin ]
208 # Look for all executables in bin/
209 for i in $(pwd)/vendor/bin/*
211 # Look for their location
212 realFile=$(readlink -f "$i")
214 # Restore write permissions
215 chmod u+wx "$(dirname "$realFile")"
216 chmod u+w "$realFile"
219 sed -e "s|#!/usr/bin/php|#!${php}/bin/php|" \
220 -e "s|#!/usr/bin/env php|#!${php}/bin/php|" \
223 chmod u+x "$realFile"
228 if [ "$removeComposerArtifacts" = "1" ]
230 # Remove composer stuff
231 rm -f composer.json composer.lock
234 # Execute post install hook
241 composer = lib.makeOverridable composer;
242 buildZipPackage = lib.makeOverridable buildZipPackage;
243 buildPackage = lib.makeOverridable buildPackage;