Run composer2nix
This commit is contained in:
parent
d415966d94
commit
988e5ee5e6
5 changed files with 364 additions and 0 deletions
1
nix/composer2nix/.gitignore
vendored
1
nix/composer2nix/.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
|
/result
|
||||||
/vendor/
|
/vendor/
|
||||||
|
|
244
nix/composer2nix/composer-env.nix
Normal file
244
nix/composer2nix/composer-env.nix
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
# This file originates from composer2nix
|
||||||
|
|
||||||
|
{ stdenv, lib, writeTextFile, fetchurl, php, unzip, phpPackages }:
|
||||||
|
|
||||||
|
let
|
||||||
|
inherit (phpPackages) composer;
|
||||||
|
|
||||||
|
filterSrc = src:
|
||||||
|
builtins.filterSource (path: type: type != "directory" || (baseNameOf path != ".git" && baseNameOf path != ".git" && baseNameOf path != ".svn")) src;
|
||||||
|
|
||||||
|
buildZipPackage = { name, src }:
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
inherit name src;
|
||||||
|
nativeBuildInputs = [ unzip ];
|
||||||
|
buildCommand = ''
|
||||||
|
shopt -s dotglob
|
||||||
|
unzip $src
|
||||||
|
baseDir=$(find . -type d -mindepth 1 -maxdepth 1)
|
||||||
|
cd $baseDir
|
||||||
|
mkdir -p $out
|
||||||
|
mv * $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
buildPackage =
|
||||||
|
{ name
|
||||||
|
, src
|
||||||
|
, packages ? {}
|
||||||
|
, devPackages ? {}
|
||||||
|
, buildInputs ? []
|
||||||
|
, symlinkDependencies ? false
|
||||||
|
, executable ? false
|
||||||
|
, removeComposerArtifacts ? false
|
||||||
|
, postInstall ? ""
|
||||||
|
, noDev ? false
|
||||||
|
, composerExtraArgs ? ""
|
||||||
|
, unpackPhase ? "true"
|
||||||
|
, buildPhase ? "true"
|
||||||
|
, ...}@args:
|
||||||
|
|
||||||
|
let
|
||||||
|
reconstructInstalled = writeTextFile {
|
||||||
|
name = "reconstructinstalled.php";
|
||||||
|
executable = true;
|
||||||
|
text = ''
|
||||||
|
#! ${php}/bin/php
|
||||||
|
<?php
|
||||||
|
if(file_exists($argv[1]))
|
||||||
|
{
|
||||||
|
$composerLockStr = file_get_contents($argv[1]);
|
||||||
|
|
||||||
|
if($composerLockStr === false)
|
||||||
|
{
|
||||||
|
fwrite(STDERR, "Cannot open composer.lock contents\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$config = json_decode($composerLockStr, true);
|
||||||
|
|
||||||
|
if(array_key_exists("packages", $config))
|
||||||
|
$allPackages = $config["packages"];
|
||||||
|
else
|
||||||
|
$allPackages = array();
|
||||||
|
|
||||||
|
${lib.optionalString (!noDev) ''
|
||||||
|
if(array_key_exists("packages-dev", $config))
|
||||||
|
$allPackages = array_merge($allPackages, $config["packages-dev"]);
|
||||||
|
''}
|
||||||
|
|
||||||
|
$packagesStr = json_encode($allPackages, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||||
|
print($packagesStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
print("[]");
|
||||||
|
?>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
constructBin = writeTextFile {
|
||||||
|
name = "constructbin.php";
|
||||||
|
executable = true;
|
||||||
|
text = ''
|
||||||
|
#! ${php}/bin/php
|
||||||
|
<?php
|
||||||
|
$composerJSONStr = file_get_contents($argv[1]);
|
||||||
|
|
||||||
|
if($composerJSONStr === false)
|
||||||
|
{
|
||||||
|
fwrite(STDERR, "Cannot open composer.json contents\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$config = json_decode($composerJSONStr, true);
|
||||||
|
|
||||||
|
if(array_key_exists("bin-dir", $config))
|
||||||
|
$binDir = $config["bin-dir"];
|
||||||
|
else
|
||||||
|
$binDir = "bin";
|
||||||
|
|
||||||
|
if(array_key_exists("bin", $config))
|
||||||
|
{
|
||||||
|
if(!file_exists("vendor/".$binDir))
|
||||||
|
mkdir("vendor/".$binDir);
|
||||||
|
|
||||||
|
foreach($config["bin"] as $bin)
|
||||||
|
symlink("../../".$bin, "vendor/".$binDir."/".basename($bin));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
bundleDependencies = dependencies:
|
||||||
|
lib.concatMapStrings (dependencyName:
|
||||||
|
let
|
||||||
|
dependency = dependencies.${dependencyName};
|
||||||
|
in
|
||||||
|
''
|
||||||
|
${if dependency.targetDir == "" then ''
|
||||||
|
vendorDir="$(dirname ${dependencyName})"
|
||||||
|
mkdir -p "$vendorDir"
|
||||||
|
${if symlinkDependencies then
|
||||||
|
''ln -s "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
|
||||||
|
else
|
||||||
|
''cp -av "${dependency.src}" "$vendorDir/$(basename "${dependencyName}")"''
|
||||||
|
}
|
||||||
|
'' else ''
|
||||||
|
namespaceDir="${dependencyName}/$(dirname "${dependency.targetDir}")"
|
||||||
|
mkdir -p "$namespaceDir"
|
||||||
|
${if symlinkDependencies then
|
||||||
|
''ln -s "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
|
||||||
|
else
|
||||||
|
''cp -av "${dependency.src}" "$namespaceDir/$(basename "${dependency.targetDir}")"''
|
||||||
|
}
|
||||||
|
''}
|
||||||
|
'') (builtins.attrNames dependencies);
|
||||||
|
|
||||||
|
extraArgs = removeAttrs args [ "packages" "devPackages" "buildInputs" ];
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation ({
|
||||||
|
buildInputs = [ php composer ] ++ buildInputs;
|
||||||
|
|
||||||
|
inherit unpackPhase buildPhase;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
${if executable then ''
|
||||||
|
mkdir -p $out/share/php
|
||||||
|
cp -av $src $out/share/php/$name
|
||||||
|
chmod -R u+w $out/share/php/$name
|
||||||
|
cd $out/share/php/$name
|
||||||
|
'' else ''
|
||||||
|
cp -av $src $out
|
||||||
|
chmod -R u+w $out
|
||||||
|
cd $out
|
||||||
|
''}
|
||||||
|
|
||||||
|
# Remove unwanted files
|
||||||
|
rm -f *.nix
|
||||||
|
|
||||||
|
export HOME=$TMPDIR
|
||||||
|
|
||||||
|
# Remove the provided vendor folder if it exists
|
||||||
|
rm -Rf vendor
|
||||||
|
|
||||||
|
# If there is no composer.lock file, compose a dummy file.
|
||||||
|
# Otherwise, composer attempts to download the package.json file from
|
||||||
|
# the registry which we do not want.
|
||||||
|
if [ ! -f composer.lock ]
|
||||||
|
then
|
||||||
|
cat > composer.lock <<EOF
|
||||||
|
{
|
||||||
|
"packages": []
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reconstruct the installed.json file from the lock file
|
||||||
|
mkdir -p vendor/composer
|
||||||
|
${php}/bin/php ${reconstructInstalled} composer.lock > vendor/composer/installed.json
|
||||||
|
|
||||||
|
# Copy or symlink the provided dependencies
|
||||||
|
cd vendor
|
||||||
|
${bundleDependencies packages}
|
||||||
|
${lib.optionalString (!noDev) (bundleDependencies devPackages)}
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Reconstruct autoload scripts
|
||||||
|
# We use the optimize feature because Nix packages cannot change after they have been built
|
||||||
|
# Using the dynamic loader for a Nix package is useless since there is nothing to dynamically reload.
|
||||||
|
composer dump-autoload --optimize ${lib.optionalString noDev "--no-dev"} ${composerExtraArgs}
|
||||||
|
|
||||||
|
# Run the install step as a validation to confirm that everything works out as expected
|
||||||
|
composer install --optimize-autoloader ${lib.optionalString noDev "--no-dev"} ${composerExtraArgs}
|
||||||
|
|
||||||
|
${lib.optionalString executable ''
|
||||||
|
# Reconstruct the bin/ folder if we deploy an executable project
|
||||||
|
${php}/bin/php ${constructBin} composer.json
|
||||||
|
ln -s $(pwd)/vendor/bin $out/bin
|
||||||
|
''}
|
||||||
|
|
||||||
|
${lib.optionalString (!symlinkDependencies) ''
|
||||||
|
# Patch the shebangs if possible
|
||||||
|
if [ -d $(pwd)/vendor/bin ]
|
||||||
|
then
|
||||||
|
# Look for all executables in bin/
|
||||||
|
for i in $(pwd)/vendor/bin/*
|
||||||
|
do
|
||||||
|
# Look for their location
|
||||||
|
realFile=$(readlink -f "$i")
|
||||||
|
|
||||||
|
# Restore write permissions
|
||||||
|
chmod u+wx "$(dirname "$realFile")"
|
||||||
|
chmod u+w "$realFile"
|
||||||
|
|
||||||
|
# Patch shebang
|
||||||
|
sed -e "s|#!/usr/bin/php|#!${php}/bin/php|" \
|
||||||
|
-e "s|#!/usr/bin/env php|#!${php}/bin/php|" \
|
||||||
|
"$realFile" > tmp
|
||||||
|
mv tmp "$realFile"
|
||||||
|
chmod u+x "$realFile"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
''}
|
||||||
|
|
||||||
|
if [ "$removeComposerArtifacts" = "1" ]
|
||||||
|
then
|
||||||
|
# Remove composer stuff
|
||||||
|
rm -f composer.json composer.lock
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Execute post install hook
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
} // extraArgs);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit filterSrc;
|
||||||
|
composer = lib.makeOverridable composer;
|
||||||
|
buildZipPackage = lib.makeOverridable buildZipPackage;
|
||||||
|
buildPackage = lib.makeOverridable buildPackage;
|
||||||
|
}
|
14
nix/composer2nix/default.nix
Normal file
14
nix/composer2nix/default.nix
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{pkgs ? import <nixpkgs> {
|
||||||
|
inherit system;
|
||||||
|
}, system ? builtins.currentSystem, noDev ? false, php ? pkgs.php, phpPackages ? pkgs.phpPackages}:
|
||||||
|
|
||||||
|
let
|
||||||
|
composerEnv = import ./composer-env.nix {
|
||||||
|
inherit (pkgs) stdenv lib writeTextFile fetchurl unzip;
|
||||||
|
inherit php phpPackages;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
import ./php-packages.nix {
|
||||||
|
inherit composerEnv noDev;
|
||||||
|
inherit (pkgs) fetchurl fetchgit fetchhg fetchsvn;
|
||||||
|
}
|
0
nix/composer2nix/notes.txt
Normal file
0
nix/composer2nix/notes.txt
Normal file
105
nix/composer2nix/php-packages.nix
Normal file
105
nix/composer2nix/php-packages.nix
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
{composerEnv, fetchurl, fetchgit ? null, fetchhg ? null, fetchsvn ? null, noDev ? false}:
|
||||||
|
|
||||||
|
let
|
||||||
|
packages = {
|
||||||
|
"psr/container" = {
|
||||||
|
targetDir = "";
|
||||||
|
src = composerEnv.buildZipPackage {
|
||||||
|
name = "psr-container-c71ecc56dfe541dbd90c5360474fbc405f8d5963";
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963";
|
||||||
|
sha256 = "1mvan38yb65hwk68hl0p7jymwzr4zfnaxmwjbw7nj3rsknvga49i";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"symfony/console" = {
|
||||||
|
targetDir = "";
|
||||||
|
src = composerEnv.buildZipPackage {
|
||||||
|
name = "symfony-console-5f360ebc65c55265a74d23d7fe27f957870158a1";
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://api.github.com/repos/symfony/console/zipball/5f360ebc65c55265a74d23d7fe27f957870158a1";
|
||||||
|
sha256 = "0y4lq8hd71pg2jwfkrmzhcy85z2rpc05wk43x9sq20pdw312fg0d";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"symfony/deprecation-contracts" = {
|
||||||
|
targetDir = "";
|
||||||
|
src = composerEnv.buildZipPackage {
|
||||||
|
name = "symfony-deprecation-contracts-63afe740e99a13ba87ec199bb07bbdee937a5b62";
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62";
|
||||||
|
sha256 = "1blzjsmk38b36l15khbx2qs3c6xqmfp32l9xxq3305ifshw7ldby";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"symfony/polyfill-ctype" = {
|
||||||
|
targetDir = "";
|
||||||
|
src = composerEnv.buildZipPackage {
|
||||||
|
name = "symfony-polyfill-ctype-a3cc8b044a6ea513310cbd48ef7333b384945638";
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638";
|
||||||
|
sha256 = "1gwalz2r31bfqldkqhw8cbxybmc1pkg74kvg07binkhk531gjqdn";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"symfony/polyfill-intl-grapheme" = {
|
||||||
|
targetDir = "";
|
||||||
|
src = composerEnv.buildZipPackage {
|
||||||
|
name = "symfony-polyfill-intl-grapheme-b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe";
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe";
|
||||||
|
sha256 = "06kbz2rqp0kyxpry055pciv02ihl7vgygigqhdqqy6q7aphg9i9a";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"symfony/polyfill-intl-normalizer" = {
|
||||||
|
targetDir = "";
|
||||||
|
src = composerEnv.buildZipPackage {
|
||||||
|
name = "symfony-polyfill-intl-normalizer-3833d7255cc303546435cb650316bff708a1c75c";
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c";
|
||||||
|
sha256 = "0qrq26nw97xfcl0p8x4ria46lk47k73vjjyqiklpw8w5cbibsfxj";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"symfony/polyfill-mbstring" = {
|
||||||
|
targetDir = "";
|
||||||
|
src = composerEnv.buildZipPackage {
|
||||||
|
name = "symfony-polyfill-mbstring-6d857f4d76bd4b343eac26d6b539585d2bc56493";
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493";
|
||||||
|
sha256 = "0g9a4jdc0gf7vilvz1yfyzj83bisaqa6j4sz0j9arwjzlc1p2708";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"symfony/service-contracts" = {
|
||||||
|
targetDir = "";
|
||||||
|
src = composerEnv.buildZipPackage {
|
||||||
|
name = "symfony-service-contracts-f021b05a130d35510bd6b25fe9053c2a8a15d5d4";
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4";
|
||||||
|
sha256 = "0gg6vg2x75gn5krzm99bkmk2xpc3n2i2xsi45gf3crgdyrh7mb37";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"symfony/string" = {
|
||||||
|
targetDir = "";
|
||||||
|
src = composerEnv.buildZipPackage {
|
||||||
|
name = "symfony-string-42f505aff654e62ac7ac2ce21033818297ca89ca";
|
||||||
|
src = fetchurl {
|
||||||
|
url = "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca";
|
||||||
|
sha256 = "02cji47gy7rhrhvmbsg2gvis4875di6d2w89kbz8n2g8w8v2yhay";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
devPackages = {};
|
||||||
|
in
|
||||||
|
composerEnv.buildPackage {
|
||||||
|
inherit packages devPackages noDev;
|
||||||
|
name = "composer2nix-example";
|
||||||
|
src = composerEnv.filterSrc ./.;
|
||||||
|
executable = false;
|
||||||
|
symlinkDependencies = false;
|
||||||
|
meta = {};
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue