Merge pull request #330634 from r-ryantm/auto-update/circumflex
[NixPkgs.git] / pkgs / servers / web-apps / bookstack / composer-env.nix
blob71714b7640082199fecf63e88d102fddf21ce7eb
1 # This file originates from composer2nix
3 { stdenv, lib, writeTextFile, fetchurl, php, unzip, phpPackages }:
5 let
6   inherit (phpPackages) composer;
8   filterSrc = src:
9     builtins.filterSource (path: type: type != "directory" || (baseNameOf path != ".git" && baseNameOf path != ".git" && baseNameOf path != ".svn")) src;
11   buildZipPackage = { name, src }:
12     stdenv.mkDerivation {
13       inherit name src;
14       nativeBuildInputs = [ unzip ];
15       buildCommand = ''
16         shopt -s dotglob
17         unzip $src
18         baseDir=$(find . -type d -mindepth 1 -maxdepth 1)
19         cd $baseDir
20         mkdir -p $out
21         mv * $out
22       '';
23     };
25   buildPackage =
26     { name
27     , src
28     , packages ? {}
29     , devPackages ? {}
30     , buildInputs ? []
31     , symlinkDependencies ? false
32     , executable ? false
33     , removeComposerArtifacts ? false
34     , postInstall ? ""
35     , noDev ? false
36     , composerExtraArgs ? ""
37     , unpackPhase ? "true"
38     , buildPhase ? "true"
39     , ...}@args:
41     let
42       reconstructInstalled = writeTextFile {
43         name = "reconstructinstalled.php";
44         executable = true;
45         text = ''
46           #! ${php}/bin/php
47           <?php
48           if(file_exists($argv[1]))
49           {
50               $composerLockStr = file_get_contents($argv[1]);
52               if($composerLockStr === false)
53               {
54                   fwrite(STDERR, "Cannot open composer.lock contents\n");
55                   exit(1);
56               }
57               else
58               {
59                   $config = json_decode($composerLockStr, true);
61                   if(array_key_exists("packages", $config))
62                       $allPackages = $config["packages"];
63                   else
64                       $allPackages = array();
66                   ${lib.optionalString (!noDev) ''
67                     if(array_key_exists("packages-dev", $config))
68                         $allPackages = array_merge($allPackages, $config["packages-dev"]);
69                   ''}
71                   $packagesStr = json_encode($allPackages, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
72                   print($packagesStr);
73               }
74           }
75           else
76               print("[]");
77           ?>
78         '';
79       };
81       constructBin = writeTextFile {
82         name = "constructbin.php";
83         executable = true;
84         text = ''
85           #! ${php}/bin/php
86           <?php
87           $composerJSONStr = file_get_contents($argv[1]);
89           if($composerJSONStr === false)
90           {
91               fwrite(STDERR, "Cannot open composer.json contents\n");
92               exit(1);
93           }
94           else
95           {
96               $config = json_decode($composerJSONStr, true);
98               if(array_key_exists("bin-dir", $config))
99                   $binDir = $config["bin-dir"];
100               else
101                   $binDir = "bin";
103               if(array_key_exists("bin", $config))
104               {
105                   if(!file_exists("vendor/".$binDir))
106                       mkdir("vendor/".$binDir);
108                   foreach($config["bin"] as $bin)
109                       symlink("../../".$bin, "vendor/".$binDir."/".basename($bin));
110               }
111           }
112           ?>
113         '';
114       };
116       bundleDependencies = dependencies:
117         lib.concatMapStrings (dependencyName:
118           let
119             dependency = dependencies.${dependencyName};
120           in
121           ''
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}")"''
127                 else
128                 ''cp -av "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
129               }
130             '' else ''
131               namespaceDir="${dependencyName}/$(dirname "${dependency.targetDir}")"
132               mkdir -p "$namespaceDir"
133               ${if symlinkDependencies then
134                 ''ln -s "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
135               else
136                 ''cp -av "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
137               }
138             ''}
139           '') (builtins.attrNames dependencies);
141       extraArgs = removeAttrs args [ "packages" "devPackages" "buildInputs" ];
142     in
143     stdenv.mkDerivation ({
144       buildInputs = [ php composer ] ++ buildInputs;
146       inherit unpackPhase buildPhase;
148       installPhase = ''
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
154         '' else ''
155           cp -av $src $out
156           chmod -R u+w $out
157           cd $out
158         ''}
160         # Remove unwanted files
161         rm -f *.nix
163         export HOME=$TMPDIR
165         # Remove the provided vendor folder if it exists
166         rm -Rf vendor
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 ]
172         then
173             cat > composer.lock <<EOF
174         {
175             "packages": []
176         }
177         EOF
178         fi
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
185         cd vendor
186         ${bundleDependencies packages}
187         ${lib.optionalString (!noDev) (bundleDependencies devPackages)}
188         cd ..
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
202         ''}
204         ${lib.optionalString (!symlinkDependencies) ''
205           # Patch the shebangs if possible
206           if [ -d $(pwd)/vendor/bin ]
207           then
208               # Look for all executables in bin/
209               for i in $(pwd)/vendor/bin/*
210               do
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"
218                   # Patch shebang
219                   sed -e "s|#!/usr/bin/php|#!${php}/bin/php|" \
220                       -e "s|#!/usr/bin/env php|#!${php}/bin/php|" \
221                       "$realFile" > tmp
222                   mv tmp "$realFile"
223                   chmod u+x "$realFile"
224               done
225           fi
226         ''}
228         if [ "$removeComposerArtifacts" = "1" ]
229         then
230             # Remove composer stuff
231             rm -f composer.json composer.lock
232         fi
234         # Execute post install hook
235         runHook postInstall
236     '';
237   } // extraArgs);
240   inherit filterSrc;
241   composer = lib.makeOverridable composer;
242   buildZipPackage = lib.makeOverridable buildZipPackage;
243   buildPackage = lib.makeOverridable buildPackage;