Skip to content

Commit 648fcf0

Browse files
committedAug 8, 2018
Package up dependencies with composer2nix
I had to patch composer2nix with: require_once(dirname(__FILE__)./../../../../vendor/autoload.php);
1 parent a7000b9 commit 648fcf0

File tree

6 files changed

+416
-20
lines changed

6 files changed

+416
-20
lines changed
 

‎default.nix

+1-18
Original file line numberDiff line numberDiff line change
@@ -68,22 +68,5 @@ EOF
6868
fi
6969
'';
7070

71-
ofborg.php = pkgs.runCommand
72-
"ofborg"
73-
{
74-
src = builtins.filterSource
75-
(path: type: !(
76-
(type == "symlink" && baseNameOf path == "result")
77-
|| (type == "directory" && baseNameOf path == ".git")
78-
))
79-
./php;
80-
}
81-
''
82-
cp -r $src ./ofborg
83-
chmod -R u+w ./ofborg
84-
cd ofborg
85-
ls -la
86-
cd ..
87-
mv ofborg $out
88-
'';
71+
ofborg.php = import ./php { inherit pkgs; };
8972
}

‎php/composer-env.nix

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

‎php/composer.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{
2+
"name": "ofborg-webhook",
23
"require": {
3-
"php-amqplib/php-amqplib": ">=2.6.1"
4+
"php-amqplib/php-amqplib": ">=2.6.1",
5+
"svanderburg/composer2nix": ">=0.0.3"
46
}
57
}

‎php/composer.lock

+84-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎php/default.nix

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{pkgs ? import <nixpkgs> {
2+
inherit system;
3+
}, system ? builtins.currentSystem, noDev ? false}:
4+
5+
let
6+
composerEnv = import ./composer-env.nix {
7+
inherit (pkgs) stdenv writeTextFile fetchurl php unzip;
8+
};
9+
in
10+
import ./php-packages.nix {
11+
inherit composerEnv noDev;
12+
inherit (pkgs) fetchurl fetchgit fetchhg fetchsvn;
13+
}

‎php/php-packages.nix

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{composerEnv, fetchurl, fetchgit ? null, fetchhg ? null, fetchsvn ? null, noDev ? false}:
2+
3+
let
4+
packages = {
5+
"php-amqplib/php-amqplib" = {
6+
targetDir = "";
7+
src = composerEnv.buildZipPackage {
8+
name = "php-amqplib-php-amqplib-dfd3694a86f1a7394d3693485259d4074a6ec79b";
9+
src = fetchurl {
10+
url = https://api.github.com/repos/php-amqplib/php-amqplib/zipball/dfd3694a86f1a7394d3693485259d4074a6ec79b;
11+
sha256 = "1dlxgdnhy8xyx8xbp1glc7igksvsqyc3yaq76irhy09djij013ip";
12+
};
13+
};
14+
};
15+
"svanderburg/composer2nix" = {
16+
targetDir = "";
17+
src = composerEnv.buildZipPackage {
18+
name = "svanderburg-composer2nix-2fb157acaf0ecbe34436195c694637396f7258a6";
19+
src = fetchurl {
20+
url = https://api.github.com/repos/svanderburg/composer2nix/zipball/2fb157acaf0ecbe34436195c694637396f7258a6;
21+
sha256 = "01i3kxgx7pcmxafclp8ib08nib1xh6nvr5sbl6y38rw19xhnwa0m";
22+
};
23+
};
24+
};
25+
"svanderburg/pndp" = {
26+
targetDir = "";
27+
src = composerEnv.buildZipPackage {
28+
name = "svanderburg-pndp-4bfe9c4120c23354ab8dc295957dc3009a39bff0";
29+
src = fetchurl {
30+
url = https://api.github.com/repos/svanderburg/pndp/zipball/4bfe9c4120c23354ab8dc295957dc3009a39bff0;
31+
sha256 = "0n2vwpwshv16bhb7a6j95m664zh4lpfa7dqmcyhmn89nxpgvg91y";
32+
};
33+
};
34+
};
35+
};
36+
devPackages = {};
37+
in
38+
composerEnv.buildPackage {
39+
inherit packages devPackages noDev;
40+
name = "ofborg-webhook";
41+
src = ./.;
42+
executable = false;
43+
symlinkDependencies = false;
44+
meta = {};
45+
}

0 commit comments

Comments
 (0)
Please sign in to comment.