Initial repo for search and displace code (written for, rather than the tools used in the processing)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
7.4 KiB

  1. # This file originates from composer2nix
  2. { stdenv, writeTextFile, fetchurl, php, unzip, phpPackages }:
  3. let
  4. inherit (phpPackages) composer;
  5. buildZipPackage = { name, src }:
  6. stdenv.mkDerivation {
  7. inherit name src;
  8. buildInputs = [ unzip ];
  9. buildCommand = ''
  10. unzip $src
  11. baseDir=$(find . -type d -mindepth 1 -maxdepth 1)
  12. cd $baseDir
  13. mkdir -p $out
  14. mv * $out
  15. '';
  16. };
  17. buildPackage =
  18. { name
  19. , src
  20. , packages ? {}
  21. , devPackages ? {}
  22. , buildInputs ? []
  23. , symlinkDependencies ? false
  24. , executable ? false
  25. , removeComposerArtifacts ? false
  26. , postInstall ? ""
  27. , noDev ? false
  28. , unpackPhase ? "true"
  29. , buildPhase ? "true"
  30. , ...}@args:
  31. let
  32. reconstructInstalled = writeTextFile {
  33. name = "reconstructinstalled.php";
  34. executable = true;
  35. text = ''
  36. #! ${php}/bin/php
  37. <?php
  38. if(file_exists($argv[1]))
  39. {
  40. $composerLockStr = file_get_contents($argv[1]);
  41. if($composerLockStr === false)
  42. {
  43. fwrite(STDERR, "Cannot open composer.lock contents\n");
  44. exit(1);
  45. }
  46. else
  47. {
  48. $config = json_decode($composerLockStr, true);
  49. if(array_key_exists("packages", $config))
  50. $allPackages = $config["packages"];
  51. else
  52. $allPackages = array();
  53. ${stdenv.lib.optionalString (!noDev) ''
  54. if(array_key_exists("packages-dev", $config))
  55. $allPackages = array_merge($allPackages, $config["packages-dev"]);
  56. ''}
  57. $packagesStr = json_encode($allPackages, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
  58. print($packagesStr);
  59. }
  60. }
  61. else
  62. print("[]");
  63. ?>
  64. '';
  65. };
  66. constructBin = writeTextFile {
  67. name = "constructbin.php";
  68. executable = true;
  69. text = ''
  70. #! ${php}/bin/php
  71. <?php
  72. $composerJSONStr = file_get_contents($argv[1]);
  73. if($composerJSONStr === false)
  74. {
  75. fwrite(STDERR, "Cannot open composer.json contents\n");
  76. exit(1);
  77. }
  78. else
  79. {
  80. $config = json_decode($composerJSONStr, true);
  81. if(array_key_exists("bin-dir", $config))
  82. $binDir = $config["bin-dir"];
  83. else
  84. $binDir = "bin";
  85. if(array_key_exists("bin", $config))
  86. {
  87. if(!file_exists("vendor/".$binDir))
  88. mkdir("vendor/".$binDir);
  89. foreach($config["bin"] as $bin)
  90. symlink("../../".$bin, "vendor/".$binDir."/".basename($bin));
  91. }
  92. }
  93. ?>
  94. '';
  95. };
  96. bundleDependencies = dependencies:
  97. stdenv.lib.concatMapStrings (dependencyName:
  98. let
  99. dependency = dependencies.${dependencyName};
  100. in
  101. ''
  102. ${if dependency.targetDir == "" then ''
  103. vendorDir="$(dirname ${dependencyName})"
  104. mkdir -p "$vendorDir"
  105. ${if symlinkDependencies then
  106. ''ln -s "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
  107. else
  108. ''cp -av "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
  109. }
  110. '' else ''
  111. namespaceDir="${dependencyName}/$(dirname "${dependency.targetDir}")"
  112. mkdir -p "$namespaceDir"
  113. ${if symlinkDependencies then
  114. ''ln -s "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
  115. else
  116. ''cp -av "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
  117. }
  118. ''}
  119. '') (builtins.attrNames dependencies);
  120. extraArgs = removeAttrs args [ "name" "packages" "devPackages" "buildInputs" ];
  121. in
  122. stdenv.mkDerivation ({
  123. name = "composer-${name}";
  124. buildInputs = [ php composer ] ++ buildInputs;
  125. inherit unpackPhase buildPhase;
  126. installPhase = ''
  127. ${if executable then ''
  128. mkdir -p $out/share/php
  129. cp -av $src $out/share/php/$name
  130. chmod -R u+w $out/share/php/$name
  131. cd $out/share/php/$name
  132. '' else ''
  133. cp -av $src $out
  134. chmod -R u+w $out
  135. cd $out
  136. ''}
  137. # Remove unwanted files
  138. rm -f *.nix
  139. export HOME=$TMPDIR
  140. # Remove the provided vendor folder if it exists
  141. rm -Rf vendor
  142. # If there is no composer.lock file, compose a dummy file.
  143. # Otherwise, composer attempts to download the package.json file from
  144. # the registry which we do not want.
  145. if [ ! -f composer.lock ]
  146. then
  147. cat > composer.lock <<EOF
  148. {
  149. "packages": []
  150. }
  151. EOF
  152. fi
  153. # Reconstruct the installed.json file from the lock file
  154. mkdir -p vendor/composer
  155. ${reconstructInstalled} composer.lock > vendor/composer/installed.json
  156. # Copy or symlink the provided dependencies
  157. cd vendor
  158. ${bundleDependencies packages}
  159. ${stdenv.lib.optionalString (!noDev) (bundleDependencies devPackages)}
  160. cd ..
  161. # Reconstruct autoload scripts
  162. # We use the optimize feature because Nix packages cannot change after they have been built
  163. # Using the dynamic loader for a Nix package is useless since there is nothing to dynamically reload.
  164. composer dump-autoload --optimize ${stdenv.lib.optionalString noDev "--no-dev"}
  165. # Run the install step as a validation to confirm that everything works out as expected
  166. composer install --optimize-autoloader ${stdenv.lib.optionalString noDev "--no-dev"}
  167. ${stdenv.lib.optionalString executable ''
  168. # Reconstruct the bin/ folder if we deploy an executable project
  169. ${constructBin} composer.json
  170. ln -s $(pwd)/vendor/bin $out/bin
  171. ''}
  172. ${stdenv.lib.optionalString (!symlinkDependencies) ''
  173. # Patch the shebangs if possible
  174. if [ -d $(pwd)/vendor/bin ]
  175. then
  176. # Look for all executables in bin/
  177. for i in $(pwd)/vendor/bin/*
  178. do
  179. # Look for their location
  180. realFile=$(readlink -f "$i")
  181. # Restore write permissions
  182. chmod u+wx "$(dirname "$realFile")"
  183. chmod u+w "$realFile"
  184. # Patch shebang
  185. sed -e "s|#!/usr/bin/php|#!${php}/bin/php|" \
  186. -e "s|#!/usr/bin/env php|#!${php}/bin/php|" \
  187. "$realFile" > tmp
  188. mv tmp "$realFile"
  189. chmod u+x "$realFile"
  190. done
  191. fi
  192. ''}
  193. if [ "$removeComposerArtifacts" = "1" ]
  194. then
  195. # Remove composer stuff
  196. rm -f composer.json composer.lock
  197. fi
  198. # Execute post install hook
  199. runHook postInstall
  200. '';
  201. } // extraArgs);
  202. in
  203. {
  204. composer = stdenv.lib.makeOverridable composer;
  205. buildZipPackage = stdenv.lib.makeOverridable buildZipPackage;
  206. buildPackage = stdenv.lib.makeOverridable buildPackage;
  207. }