@@ -0,0 +1,55 | |||
|
1 | ||
|
2 | ============================== | |
|
3 | Generate the Nix expressions | |
|
4 | ============================== | |
|
5 | ||
|
6 | Details can be found in the repository of `RhodeCode Enterprise CE`_ inside of | |
|
7 | the file `docs/contributing/dependencies.rst`. | |
|
8 | ||
|
9 | Start the environment as follows: | |
|
10 | ||
|
11 | .. code:: shell | |
|
12 | ||
|
13 | nix-shell pkgs/shell-generate.nix | |
|
14 | ||
|
15 | ||
|
16 | ||
|
17 | Python dependencies | |
|
18 | =================== | |
|
19 | ||
|
20 | .. code:: shell | |
|
21 | ||
|
22 | pip2nix generate --licenses | |
|
23 | # or | |
|
24 | nix-shell pkgs/shell-generate.nix --command "pip2nix generate --licenses" | |
|
25 | ||
|
26 | ||
|
27 | NodeJS dependencies | |
|
28 | =================== | |
|
29 | ||
|
30 | .. code:: shell | |
|
31 | ||
|
32 | # switch to pkgs dir | |
|
33 | pushd pkgs | |
|
34 | node2nix --input ../package.json \ | |
|
35 | -o node-packages.nix \ | |
|
36 | -e node-env.nix \ | |
|
37 | -c node-default.nix \ | |
|
38 | -d --flatten --nodejs-6 | |
|
39 | popd | |
|
40 | ||
|
41 | ||
|
42 | ||
|
43 | Bower dependencies | |
|
44 | ================== | |
|
45 | ||
|
46 | .. code:: shell | |
|
47 | ||
|
48 | bower2nix bower.json pkgs/bower-packages.nix | |
|
49 | # or | |
|
50 | nix-shell pkgs/shell-generate.nix --command "bower2nix bower.json pkgs/bower-packages.nix" | |
|
51 | ||
|
52 | ||
|
53 | .. Links | |
|
54 | ||
|
55 | .. _RhodeCode Enterprise CE: https://code.rhodecode.com/rhodecode-enterprise-ce |
@@ -0,0 +1,17 | |||
|
1 | { pkgs | |
|
2 | , pythonPackages | |
|
3 | }: | |
|
4 | ||
|
5 | rec { | |
|
6 | pip2nix-src = pkgs.fetchzip { | |
|
7 | url = https://github.com/johbo/pip2nix/archive/51e6fdae34d0e8ded9efeef7a8601730249687a6.tar.gz; | |
|
8 | sha256 = "02a4jjgi7lsvf8mhrxsd56s9a3yg20081rl9bgc2m84w60v2gbz2"; | |
|
9 | }; | |
|
10 | ||
|
11 | pip2nix = import pip2nix-src { | |
|
12 | inherit | |
|
13 | pkgs | |
|
14 | pythonPackages; | |
|
15 | }; | |
|
16 | ||
|
17 | } |
@@ -0,0 +1,52 | |||
|
1 | { pkgs ? (import <nixpkgs> {}) | |
|
2 | , pythonPackages ? "python27Packages" | |
|
3 | }: | |
|
4 | ||
|
5 | with pkgs.lib; | |
|
6 | ||
|
7 | let _pythonPackages = pythonPackages; in | |
|
8 | let | |
|
9 | pythonPackages = getAttr _pythonPackages pkgs; | |
|
10 | ||
|
11 | pip2nix = import ./nix-common/pip2nix.nix { | |
|
12 | inherit | |
|
13 | pkgs | |
|
14 | pythonPackages; | |
|
15 | }; | |
|
16 | ||
|
17 | in | |
|
18 | ||
|
19 | pkgs.stdenv.mkDerivation { | |
|
20 | name = "pip2nix-generated"; | |
|
21 | buildInputs = [ | |
|
22 | # Allows to generate python packages | |
|
23 | pip2nix.pip2nix | |
|
24 | pythonPackages.pip-tools | |
|
25 | ||
|
26 | # Allows to generate bower dependencies | |
|
27 | pkgs.nodePackages.bower2nix | |
|
28 | ||
|
29 | # Allows to generate node dependencies | |
|
30 | pkgs.nodePackages.node2nix | |
|
31 | ||
|
32 | # We need mysql_config to be around | |
|
33 | pkgs.mysql | |
|
34 | ||
|
35 | # We need postgresql to be around | |
|
36 | pkgs.postgresql | |
|
37 | ||
|
38 | # Curl is needed for pycurl | |
|
39 | pkgs.curl | |
|
40 | ]; | |
|
41 | ||
|
42 | shellHook = '' | |
|
43 | runHook preShellHook | |
|
44 | runHook postShellHook | |
|
45 | ''; | |
|
46 | ||
|
47 | preShellHook = '' | |
|
48 | echo "Starting Generate Shell" | |
|
49 | # Custom prompt to distinguish from other dev envs. | |
|
50 | export PS1="\n\[\033[1;32m\][Generate-shell:\w]$\[\033[0m\] " | |
|
51 | ''; | |
|
52 | } |
@@ -10,7 +10,7 | |||
|
10 | 10 | "paper-tooltip": "PolymerElements/paper-tooltip#^1.1.2", |
|
11 | 11 | "paper-toast": "PolymerElements/paper-toast#^1.3.0", |
|
12 | 12 | "paper-toggle-button": "PolymerElements/paper-toggle-button#^1.2.0", |
|
13 |
"iron-ajax": "PolymerElements/iron-ajax#^1.4. |
|
|
13 | "iron-ajax": "PolymerElements/iron-ajax#^1.4.4", | |
|
14 | 14 | "iron-autogrow-textarea": "PolymerElements/iron-autogrow-textarea#^1.0.13", |
|
15 | 15 | "iron-a11y-keys": "PolymerElements/iron-a11y-keys#^1.0.6" |
|
16 | 16 | } |
@@ -1,41 +1,40 | |||
|
1 | 1 | # Nix environment for the community edition |
|
2 | 2 | # |
|
3 |
# This shall be as lean as possible, just producing the |
|
|
3 | # This shall be as lean as possible, just producing the enterprise-ce | |
|
4 | 4 | # derivation. For advanced tweaks to pimp up the development environment we use |
|
5 | 5 | # "shell.nix" so that it does not have to clutter this file. |
|
6 | # | |
|
7 | # Configuration, set values in "~/.nixpkgs/config.nix". | |
|
8 | # example | |
|
9 | # { | |
|
10 | # # Thoughts on how to configure the dev environment | |
|
11 | # rc = { | |
|
12 | # codeInternalUrl = "https://usr:token@internal-code.rhodecode.com"; | |
|
13 | # sources = { | |
|
14 | # rhodecode-vcsserver = "/home/user/work/rhodecode-vcsserver"; | |
|
15 | # rhodecode-enterprise-ce = "/home/user/work/rhodecode-enterprise-ce"; | |
|
16 | # rhodecode-enterprise-ee = "/home/user/work/rhodecode-enterprise-ee"; | |
|
17 | # }; | |
|
18 | # }; | |
|
19 | # } | |
|
6 | 20 | |
|
7 | 21 | args@ |
|
8 | 22 | { pythonPackages ? "python27Packages" |
|
9 | 23 | , pythonExternalOverrides ? self: super: {} |
|
10 |
, doCheck ? |
|
|
24 | , doCheck ? false | |
|
11 | 25 | , ... |
|
12 | 26 | }: |
|
13 | 27 | |
|
14 | 28 | let |
|
15 | ||
|
16 | 29 | # Use nixpkgs from args or import them. We use this indirect approach |
|
17 | 30 | # through args to be able to use the name `pkgs` for our customized packages. |
|
18 | 31 | # Otherwise we will end up with an infinite recursion. |
|
19 |
|
|
|
32 | pkgs = args.pkgs or (import <nixpkgs> { }); | |
|
20 | 33 | |
|
21 | # johbo: Interim bridge which allows us to build with the upcoming | |
|
22 | # nixos.16.09 branch (unstable at the moment of writing this note) and the | |
|
23 | # current stable nixos-16.03. | |
|
24 | backwardsCompatibleFetchgit = { ... }@args: | |
|
25 | let | |
|
26 | origSources = nixpkgs.fetchgit args; | |
|
27 | in | |
|
28 | nixpkgs.lib.overrideDerivation origSources (oldAttrs: { | |
|
29 | NIX_PREFETCH_GIT_CHECKOUT_HOOK = '' | |
|
30 | find $out -name '.git*' -print0 | xargs -0 rm -rf | |
|
31 | ''; | |
|
32 | }); | |
|
33 | ||
|
34 | # Create a customized version of nixpkgs which should be used throughout the | |
|
35 | # rest of this file. | |
|
36 | pkgs = nixpkgs.overridePackages (self: super: { | |
|
37 | fetchgit = backwardsCompatibleFetchgit; | |
|
38 | }); | |
|
34 | # Works with the new python-packages, still can fallback to the old | |
|
35 | # variant. | |
|
36 | basePythonPackagesUnfix = basePythonPackages.__unfix__ or ( | |
|
37 | self: basePythonPackages.override (a: { inherit self; })); | |
|
39 | 38 | |
|
40 | 39 | # Evaluates to the last segment of a file system path. |
|
41 | 40 | basename = path: with pkgs.lib; last (splitString "/" path); |
@@ -46,7 +45,7 let | |||
|
46 | 45 | ext = last (splitString "." path); |
|
47 | 46 | in |
|
48 | 47 | !builtins.elem (basename path) [ |
|
49 | ".git" ".hg" "__pycache__" ".eggs" | |
|
48 | ".git" ".hg" "__pycache__" ".eggs" ".idea" ".dev" | |
|
50 | 49 | "bower_components" "node_modules" |
|
51 | 50 | "build" "data" "result" "tmp"] && |
|
52 | 51 | !builtins.elem ext ["egg-info" "pyc"] && |
@@ -54,18 +53,20 let | |||
|
54 | 53 | # it would still be good to restore it since we want to ignore "result-*". |
|
55 | 54 | !hasPrefix "result" path; |
|
56 | 55 | |
|
57 | basePythonPackages = with builtins; if isAttrs pythonPackages | |
|
58 | then pythonPackages | |
|
59 | else getAttr pythonPackages pkgs; | |
|
56 | sources = | |
|
57 | let | |
|
58 | inherit (pkgs.lib) all isString attrValues; | |
|
59 | sourcesConfig = pkgs.config.rc.sources or {}; | |
|
60 | in | |
|
61 | # Ensure that sources are configured as strings. Using a path | |
|
62 | # would result in a copy into the nix store. | |
|
63 | assert all isString (attrValues sourcesConfig); | |
|
64 | sourcesConfig; | |
|
60 | 65 | |
|
61 | buildBowerComponents = | |
|
62 | pkgs.buildBowerComponents or | |
|
63 | (import ./pkgs/backport-16.03-build-bower-components.nix { inherit pkgs; }); | |
|
64 | ||
|
65 | sources = pkgs.config.rc.sources or {}; | |
|
66 | version = builtins.readFile ./rhodecode/VERSION; | |
|
66 | version = builtins.readFile "${rhodecode-enterprise-ce-src}/rhodecode/VERSION"; | |
|
67 | 67 | rhodecode-enterprise-ce-src = builtins.filterSource src-filter ./.; |
|
68 | 68 | |
|
69 | buildBowerComponents = pkgs.buildBowerComponents; | |
|
69 | 70 | nodeEnv = import ./pkgs/node-default.nix { |
|
70 | 71 | inherit pkgs; |
|
71 | 72 | }; |
@@ -77,133 +78,145 let | |||
|
77 | 78 | src = rhodecode-enterprise-ce-src; |
|
78 | 79 | }; |
|
79 | 80 | |
|
80 | pythonGeneratedPackages = self: basePythonPackages.override (a: { | |
|
81 | inherit self; | |
|
82 | }) | |
|
83 | // (scopedImport { | |
|
84 | self = self; | |
|
85 | super = basePythonPackages; | |
|
86 | inherit pkgs; | |
|
87 | inherit (pkgs) fetchurl fetchgit; | |
|
88 | } ./pkgs/python-packages.nix); | |
|
81 | rhodecode-testdata-src = sources.rhodecode-testdata or ( | |
|
82 | pkgs.fetchhg { | |
|
83 | url = "https://code.rhodecode.com/upstream/rc_testdata"; | |
|
84 | rev = "v0.10.0"; | |
|
85 | sha256 = "0zn9swwvx4vgw4qn8q3ri26vvzgrxn15x6xnjrysi1bwmz01qjl0"; | |
|
86 | }); | |
|
89 | 87 | |
|
90 | pythonOverrides = import ./pkgs/python-packages-overrides.nix { | |
|
91 |
|
|
|
92 | basePythonPackages | |
|
93 |
|
|
|
88 | rhodecode-testdata = import "${rhodecode-testdata-src}/default.nix" { | |
|
89 | inherit | |
|
90 | doCheck | |
|
91 | pkgs | |
|
92 | pythonPackages; | |
|
94 | 93 | }; |
|
95 | 94 | |
|
96 | 95 | pythonLocalOverrides = self: super: { |
|
97 | 96 | rhodecode-enterprise-ce = |
|
98 | 97 | let |
|
99 | 98 | linkNodeAndBowerPackages = '' |
|
100 | echo "Export RhodeCode CE path" | |
|
101 | 99 | export RHODECODE_CE_PATH=${rhodecode-enterprise-ce-src} |
|
102 | echo "Link node packages" | |
|
100 | ||
|
101 | echo "[BEGIN]: Link node packages" | |
|
103 | 102 | rm -fr node_modules |
|
104 | 103 | mkdir node_modules |
|
105 | 104 | # johbo: Linking individual packages allows us to run "npm install" |
|
106 | 105 | # inside of a shell to try things out. Re-entering the shell will |
|
107 | 106 | # restore a clean environment. |
|
108 | 107 | ln -s ${nodeDependencies}/lib/node_modules/* node_modules/ |
|
108 | echo "[DONE]: Link node packages" | |
|
109 | 109 | |
|
110 |
echo " |
|
|
111 | ||
|
112 | echo "Link bower packages" | |
|
110 | echo "[BEGIN]: Link bower packages" | |
|
113 | 111 | rm -fr bower_components |
|
114 | 112 | mkdir bower_components |
|
113 | ln -s ${bowerComponents}/bower_components/* bower_components/ | |
|
114 | echo "[DONE]: Link bower packages" | |
|
115 | ''; | |
|
115 | 116 |
|
|
116 | ln -s ${bowerComponents}/bower_components/* bower_components/ | |
|
117 | echo "DONE: Link bower packages" | |
|
118 | ''; | |
|
117 | releaseName = "RhodeCodeEnterpriseCE-${version}"; | |
|
119 | 118 | in super.rhodecode-enterprise-ce.override (attrs: { |
|
120 | ||
|
121 | 119 | inherit |
|
122 | 120 | doCheck |
|
123 | 121 | version; |
|
122 | ||
|
124 | 123 | name = "rhodecode-enterprise-ce-${version}"; |
|
125 | releaseName = "RhodeCodeEnterpriseCE-${version}"; | |
|
124 | releaseName = releaseName; | |
|
126 | 125 | src = rhodecode-enterprise-ce-src; |
|
127 | 126 | dontStrip = true; # prevent strip, we don't need it. |
|
128 | 127 | |
|
129 | buildInputs = | |
|
130 | attrs.buildInputs ++ | |
|
131 | (with self; [ | |
|
132 | pkgs.nodePackages.bower | |
|
133 | pkgs.nodePackages.grunt-cli | |
|
134 | pkgs.subversion | |
|
135 | rhodecode-testdata | |
|
136 | ]); | |
|
137 | ||
|
138 | #TODO: either move this into overrides, OR use the new machanics from | |
|
139 | # pip2nix and requiremtn.txt file | |
|
140 | propagatedBuildInputs = attrs.propagatedBuildInputs ++ (with self; [ | |
|
141 | rhodecode-tools | |
|
142 | ]); | |
|
143 | ||
|
144 | # TODO: johbo: Make a nicer way to expose the parts. Maybe | |
|
145 | # pkgs/default.nix? | |
|
128 | # expose following attributed outside | |
|
146 | 129 | passthru = { |
|
147 | 130 | inherit |
|
131 | rhodecode-testdata | |
|
148 | 132 | bowerComponents |
|
149 | 133 | linkNodeAndBowerPackages |
|
150 | 134 | myPythonPackagesUnfix |
|
151 |
pythonLocalOverrides |
|
|
135 | pythonLocalOverrides | |
|
136 | pythonCommunityOverrides; | |
|
137 | ||
|
152 | 138 | pythonPackages = self; |
|
153 | 139 | }; |
|
154 | 140 | |
|
141 | buildInputs = | |
|
142 | attrs.buildInputs or [] ++ [ | |
|
143 | rhodecode-testdata | |
|
144 | pkgs.nodePackages.bower | |
|
145 | pkgs.nodePackages.grunt-cli | |
|
146 | ]; | |
|
147 | ||
|
148 | #NOTE: option to inject additional propagatedBuildInputs | |
|
149 | propagatedBuildInputs = | |
|
150 | attrs.propagatedBuildInputs or [] ++ [ | |
|
151 | ||
|
152 | ]; | |
|
153 | ||
|
155 | 154 | LC_ALL = "en_US.UTF-8"; |
|
156 | 155 | LOCALE_ARCHIVE = |
|
157 |
if pkgs.stdenv |
|
|
156 | if pkgs.stdenv.isLinux | |
|
158 | 157 | then "${pkgs.glibcLocales}/lib/locale/locale-archive" |
|
159 | 158 | else ""; |
|
160 | 159 | |
|
160 | # Add bin directory to path so that tests can find 'rhodecode'. | |
|
161 | 161 | preCheck = '' |
|
162 | 162 | export PATH="$out/bin:$PATH" |
|
163 | 163 | ''; |
|
164 | 164 | |
|
165 | # custom check phase for testing | |
|
166 | checkPhase = '' | |
|
167 | runHook preCheck | |
|
168 | PYTHONHASHSEED=random py.test -vv -p no:sugar -r xw --cov-config=.coveragerc --cov=rhodecode --cov-report=term-missing rhodecode | |
|
169 | runHook postCheck | |
|
170 | ''; | |
|
171 | ||
|
165 | 172 | postCheck = '' |
|
166 | rm -rf $out/lib/${self.python.libPrefix}/site-packages/pytest_pylons | |
|
173 | echo "Cleanup of rhodecode/tests" | |
|
167 | 174 | rm -rf $out/lib/${self.python.libPrefix}/site-packages/rhodecode/tests |
|
168 | 175 | ''; |
|
169 | 176 | |
|
170 | preBuild = linkNodeAndBowerPackages + '' | |
|
177 | preBuild = '' | |
|
178 | ||
|
179 | echo "Building frontend assets" | |
|
180 | ${linkNodeAndBowerPackages} | |
|
171 | 181 | grunt |
|
172 | 182 | rm -fr node_modules |
|
173 | 183 | ''; |
|
174 | 184 | |
|
175 | 185 | postInstall = '' |
|
176 | echo "Writing meta information for rccontrol to nix-support/rccontrol" | |
|
186 | echo "Writing enterprise-ce meta information for rccontrol to nix-support/rccontrol" | |
|
177 | 187 | mkdir -p $out/nix-support/rccontrol |
|
178 | 188 | cp -v rhodecode/VERSION $out/nix-support/rccontrol/version |
|
179 |
echo "DONE: |
|
|
189 | echo "[DONE]: enterprise-ce meta information for rccontrol written" | |
|
190 | ||
|
191 | mkdir -p $out/etc | |
|
192 | cp configs/production.ini $out/etc | |
|
193 | echo "[DONE]: saved enterprise-ce production.ini into $out/etc" | |
|
180 | 194 | |
|
181 | 195 | # python based programs need to be wrapped |
|
182 | #ln -s ${self.python}/bin/* $out/bin/ | |
|
196 | mkdir -p $out/bin | |
|
197 | # rhodecode-tools | |
|
198 | ln -s ${self.rhodecode-tools}/bin/rhodecode-* $out/bin/ | |
|
199 | ||
|
200 | # required binaries from dependencies | |
|
201 | #ln -s ${self.python}/bin/python $out/bin | |
|
183 | 202 | ln -s ${self.pyramid}/bin/* $out/bin/ |
|
184 | 203 | ln -s ${self.gunicorn}/bin/gunicorn $out/bin/ |
|
185 | 204 | ln -s ${self.supervisor}/bin/supervisor* $out/bin/ |
|
186 | 205 | ln -s ${self.pastescript}/bin/paster $out/bin/ |
|
187 | 206 | ln -s ${self.channelstream}/bin/channelstream $out/bin/ |
|
188 | 207 | ln -s ${self.celery}/bin/celery $out/bin/ |
|
208 | echo "[DONE]: created symlinks into $out/bin" | |
|
189 | 209 | |
|
190 | # rhodecode-tools | |
|
191 | ln -s ${self.rhodecode-tools}/bin/rhodecode-* $out/bin/ | |
|
192 | ||
|
193 | # note that condition should be restricted when adding further tools | |
|
194 | 210 | for file in $out/bin/*; |
|
195 | 211 | do |
|
196 | 212 | wrapProgram $file \ |
|
197 |
|
|
|
198 |
|
|
|
199 |
|
|
|
213 | --prefix PATH : $PATH \ | |
|
214 | --prefix PYTHONPATH : $PYTHONPATH \ | |
|
215 | --set PYTHONHASHSEED random | |
|
200 | 216 | done |
|
201 | 217 | |
|
202 | mkdir $out/etc | |
|
203 | cp configs/production.ini $out/etc | |
|
218 | echo "[DONE]: enterprise-ce binary wrapping" | |
|
204 | 219 | |
|
205 | ||
|
206 | # TODO: johbo: Make part of ac-tests | |
|
207 | 220 | if [ ! -f rhodecode/public/js/scripts.js ]; then |
|
208 | 221 | echo "Missing scripts.js" |
|
209 | 222 | exit 1 |
@@ -213,31 +226,33 let | |||
|
213 | 226 | exit 1 |
|
214 | 227 | fi |
|
215 | 228 | ''; |
|
216 | ||
|
217 | 229 | }); |
|
218 | 230 | |
|
219 | rhodecode-testdata = import "${rhodecode-testdata-src}/default.nix" { | |
|
220 | inherit | |
|
221 | doCheck | |
|
222 | pkgs | |
|
223 | pythonPackages; | |
|
224 | }; | |
|
225 | ||
|
226 | 231 | }; |
|
227 | 232 | |
|
228 | rhodecode-testdata-src = sources.rhodecode-testdata or ( | |
|
229 | pkgs.fetchhg { | |
|
230 | url = "https://code.rhodecode.com/upstream/rc_testdata"; | |
|
231 | rev = "v0.10.0"; | |
|
232 | sha256 = "0zn9swwvx4vgw4qn8q3ri26vvzgrxn15x6xnjrysi1bwmz01qjl0"; | |
|
233 | }); | |
|
233 | basePythonPackages = with builtins; | |
|
234 | if isAttrs pythonPackages then | |
|
235 | pythonPackages | |
|
236 | else | |
|
237 | getAttr pythonPackages pkgs; | |
|
238 | ||
|
239 | pythonGeneratedPackages = import ./pkgs/python-packages.nix { | |
|
240 | inherit pkgs; | |
|
241 | inherit (pkgs) fetchurl fetchgit fetchhg; | |
|
242 | }; | |
|
243 | ||
|
244 | pythonCommunityOverrides = import ./pkgs/python-packages-overrides.nix { | |
|
245 | inherit pkgs basePythonPackages; | |
|
246 | }; | |
|
234 | 247 | |
|
235 | 248 | # Apply all overrides and fix the final package set |
|
236 | 249 | myPythonPackagesUnfix = with pkgs.lib; |
|
237 | 250 | (extends pythonExternalOverrides |
|
238 | 251 | (extends pythonLocalOverrides |
|
239 | (extends pythonOverrides | |
|
240 |
|
|
|
252 | (extends pythonCommunityOverrides | |
|
253 | (extends pythonGeneratedPackages | |
|
254 | basePythonPackagesUnfix)))); | |
|
255 | ||
|
241 | 256 | myPythonPackages = (pkgs.lib.fix myPythonPackagesUnfix); |
|
242 | 257 | |
|
243 | 258 | in myPythonPackages.rhodecode-enterprise-ce |
@@ -47,7 +47,7 Switch nix to the latest STABLE channel | |||
|
47 | 47 | |
|
48 | 48 | run:: |
|
49 | 49 | |
|
50 |
nix-channel --add https://nixos.org/channels/nixos-1 |
|
|
50 | nix-channel --add https://nixos.org/channels/nixos-18.03 nixpkgs | |
|
51 | 51 | |
|
52 | 52 | Followed by:: |
|
53 | 53 |
@@ -1,6 +1,13 | |||
|
1 | 1 | { |
|
2 | 2 | "name": "rhodecode-enterprise", |
|
3 |
"version": "0.0 |
|
|
3 | "version": "1.0.0", | |
|
4 | "private": true, | |
|
5 | "description" : "RhodeCode JS packaged", | |
|
6 | "license": "SEE LICENSE IN LICENSE.txt", | |
|
7 | "repository" : { | |
|
8 | "type" : "hg", | |
|
9 | "url" : "https://code.rhodecode.com/rhodecode-enterprise-ce" | |
|
10 | }, | |
|
4 | 11 | "devDependencies": { |
|
5 | 12 | "grunt": "^0.4.5", |
|
6 | 13 | "grunt-contrib-copy": "^1.0.0", |
@@ -14,7 +21,7 | |||
|
14 | 21 | "grunt-vulcanize": "^1.0.0", |
|
15 | 22 | "node2nix": "^1.0.0", |
|
16 | 23 | "jshint": "^2.9.1-rc3", |
|
17 |
"bower": "^1. |
|
|
24 | "bower": "^1.8.4", | |
|
18 | 25 | "jquery": "1.11.3", |
|
19 | 26 | "favico.js": "^0.3.10", |
|
20 | 27 | "clipboard": "^1.7.1", |
@@ -1,33 +1,34 | |||
|
1 | # Generated by bower2nix v3.2.0 (https://github.com/rvl/bower2nix) | |
|
1 | 2 | { fetchbower, buildEnv }: |
|
2 | 3 | buildEnv { name = "bower-env"; ignoreCollisions = true; paths = [ |
|
3 |
(fetchbower "webcomponentsjs" "0.7.2 |
|
|
4 |
(fetchbower "polymer" "Polymer/polymer#1. |
|
|
5 |
(fetchbower "paper-button" "PolymerElements/paper-button#1.0.1 |
|
|
6 |
(fetchbower "paper-spinner" "PolymerElements/paper-spinner#1.2. |
|
|
7 |
(fetchbower "paper-tooltip" "PolymerElements/paper-tooltip#1.1. |
|
|
8 |
(fetchbower "paper-toast" "PolymerElements/paper-toast#1.3. |
|
|
9 |
(fetchbower "paper-toggle-button" "PolymerElements/paper-toggle-button#1. |
|
|
10 |
(fetchbower "iron-ajax" "PolymerElements/iron-ajax#1.4.4" "PolymerElements/iron-ajax#^1.4.4" "0jp |
|
|
11 |
(fetchbower "iron-autogrow-textarea" "PolymerElements/iron-autogrow-textarea#1.0.1 |
|
|
12 |
(fetchbower "iron-a11y-keys" "PolymerElements/iron-a11y-keys#1.0. |
|
|
13 |
(fetchbower "iron-flex-layout" "PolymerElements/iron-flex-layout#1.3. |
|
|
14 |
(fetchbower "paper-behaviors" "PolymerElements/paper-behaviors#1.0.1 |
|
|
15 |
(fetchbower "paper-material" "PolymerElements/paper-material#1.0. |
|
|
16 |
(fetchbower "paper-styles" "PolymerElements/paper-styles#1.1 |
|
|
17 |
(fetchbower "neon-animation" "PolymerElements/neon-animation#1.2. |
|
|
18 |
(fetchbower "iron-a11y-announcer" "PolymerElements/iron-a11y-announcer#1.0. |
|
|
19 |
(fetchbower "iron-overlay-behavior" "PolymerElements/iron-overlay-behavior#1. |
|
|
20 |
(fetchbower "iron-fit-behavior" "PolymerElements/iron-fit-behavior#1.2. |
|
|
21 |
(fetchbower "iron-checked-element-behavior" "PolymerElements/iron-checked-element-behavior#1.0. |
|
|
22 |
(fetchbower "promise-polyfill" "polymerlabs/promise-polyfill#1.0.1" "polymerlabs/promise-polyfill#^1.0.0" "0 |
|
|
23 |
(fetchbower "iron-behaviors" "PolymerElements/iron-behaviors#1.0.1 |
|
|
24 |
(fetchbower "iron-validatable-behavior" "PolymerElements/iron-validatable-behavior#1.1. |
|
|
25 |
(fetchbower "iron-form-element-behavior" "PolymerElements/iron-form-element-behavior#1.0. |
|
|
26 |
(fetchbower "iron-a11y-keys-behavior" " |
|
|
27 |
(fetchbower "paper-ripple" "PolymerElements/paper-ripple#1.0. |
|
|
28 |
(fetchbower "font-roboto" "PolymerElements/font-roboto#1.0 |
|
|
29 |
(fetchbower "iron-meta" "PolymerElements/iron-meta#1.1. |
|
|
30 |
(fetchbower "iron-resizable-behavior" "PolymerElements/iron-resizable-behavior#1.0. |
|
|
31 |
(fetchbower "iron-selector" "PolymerElements/iron-selector#1.5. |
|
|
32 |
(fetchbower "web-animations-js" "web-animations/web-animations-js#2. |
|
|
4 | (fetchbower "webcomponentsjs" "0.7.24" "^0.7.22" "0d6hfsd51n7qykzci9cw5vlsrajvffaf5ic3azlp2rfz76m651qj") | |
|
5 | (fetchbower "polymer" "Polymer/polymer#1.11.3" "Polymer/polymer#^1.6.1" "0n11ag2pmczw5yv3m76bh0a7hvicqvcaiv7knixx1r704pw107s6") | |
|
6 | (fetchbower "paper-button" "PolymerElements/paper-button#1.0.15" "PolymerElements/paper-button#^1.0.13" "0zabrp8p4s9md1hlwg0rqmbx0k87a41lsg9pzk747hcb349gblg0") | |
|
7 | (fetchbower "paper-spinner" "PolymerElements/paper-spinner#1.2.1" "PolymerElements/paper-spinner#^1.2.0" "0d6xc9fd2ipcli7w77yrn1k0z9j373c9y1f16db2840cyb4rvii8") | |
|
8 | (fetchbower "paper-tooltip" "PolymerElements/paper-tooltip#1.1.4" "PolymerElements/paper-tooltip#^1.1.2" "0j8s09dxqql8mgnvb7x382scq98xk2vjgylk06bsd1gphp3d3qzm") | |
|
9 | (fetchbower "paper-toast" "PolymerElements/paper-toast#1.3.1" "PolymerElements/paper-toast#^1.3.0" "1s0csv8dwgdyg4psq1zrd6vivlpsgzi4sjqllwqmlwhfnxfl5ql4") | |
|
10 | (fetchbower "paper-toggle-button" "PolymerElements/paper-toggle-button#1.3.0" "PolymerElements/paper-toggle-button#^1.2.0" "0hvv2y406lzlrkkcmv9nnd99bmcgcrhcx86q3axxv8k3580gqq97") | |
|
11 | (fetchbower "iron-ajax" "PolymerElements/iron-ajax#1.4.4" "PolymerElements/iron-ajax#^1.4.4" "0vs4dqcw5y02kj11ivzs901s5nwn97fk01xz2jmpy2fgh6l9q5yr") | |
|
12 | (fetchbower "iron-autogrow-textarea" "PolymerElements/iron-autogrow-textarea#1.0.15" "PolymerElements/iron-autogrow-textarea#^1.0.13" "1jw40ki5w21il0i9pwjywk4y6mk9lrj8fm57vfg9nlpbiqm2vswb") | |
|
13 | (fetchbower "iron-a11y-keys" "PolymerElements/iron-a11y-keys#1.0.9" "PolymerElements/iron-a11y-keys#^1.0.6" "07c2wm1p9g52qidl67a43yb7pzd88ygycgghlwzjbh2vkwrs40kp") | |
|
14 | (fetchbower "iron-flex-layout" "PolymerElements/iron-flex-layout#1.3.9" "PolymerElements/iron-flex-layout#^1.0.0" "1r54la4n8n0lq97vdxnlpdrarxsiwp2b3vfvby9il3j4y4s8vi4h") | |
|
15 | (fetchbower "paper-behaviors" "PolymerElements/paper-behaviors#1.0.13" "PolymerElements/paper-behaviors#^1.0.0" "0yljykkdg9p67dinplmp6hc5ma6sp95ykah8kz6id5z8gjmsd05b") | |
|
16 | (fetchbower "paper-material" "PolymerElements/paper-material#1.0.7" "PolymerElements/paper-material#^1.0.0" "1q9r3i5f61y6hmd18h3fcmn7y29yznraz83f9256z8cc0vglfjdb") | |
|
17 | (fetchbower "paper-styles" "PolymerElements/paper-styles#1.3.1" "PolymerElements/paper-styles#^1.0.0" "11fcxp9kx6sqp2yq0883psn8xyw5d3i753mimqbx8aqa5abvrk4q") | |
|
18 | (fetchbower "neon-animation" "PolymerElements/neon-animation#1.2.5" "PolymerElements/neon-animation#^1.0.0" "144sq9ijw1nnp2jagpa1ammrc018kp1y6nlmgq1v1iishv4ylsl5") | |
|
19 | (fetchbower "iron-a11y-announcer" "PolymerElements/iron-a11y-announcer#1.0.6" "PolymerElements/iron-a11y-announcer#^1.0.0" "1az02v91s17v9bir868pifv0s2lwxchm0i4l20176f98366813zk") | |
|
20 | (fetchbower "iron-overlay-behavior" "PolymerElements/iron-overlay-behavior#1.10.4" "PolymerElements/iron-overlay-behavior#^1.0.9" "0px6s756cgqzxzq53fgk1297j07gyfykqkhdzmj9fwyyrwiv1g8z") | |
|
21 | (fetchbower "iron-fit-behavior" "PolymerElements/iron-fit-behavior#1.2.7" "PolymerElements/iron-fit-behavior#^1.1.0" "0b864x9cdxadvzkdcn1d3yvi32kqccfv8j467337rgcq193l60jb") | |
|
22 | (fetchbower "iron-checked-element-behavior" "PolymerElements/iron-checked-element-behavior#1.0.6" "PolymerElements/iron-checked-element-behavior#^1.0.0" "165nh5vkdsr4d5vkq4sj1sz0igfy6vgx844ys164mqg8gkjncvxm") | |
|
23 | (fetchbower "promise-polyfill" "polymerlabs/promise-polyfill#1.0.1" "polymerlabs/promise-polyfill#^1.0.0" "0warxr9fk2d3cvgiq81djxwiky73gxxr5s3xa97d3c83q1lidlzy") | |
|
24 | (fetchbower "iron-behaviors" "PolymerElements/iron-behaviors#1.0.18" "PolymerElements/iron-behaviors#^1.0.0" "1icx212kh1cfdvk3v7pdqic9c48pdhnknq8ajx0dlps1l5sm69xh") | |
|
25 | (fetchbower "iron-validatable-behavior" "PolymerElements/iron-validatable-behavior#1.1.2" "PolymerElements/iron-validatable-behavior#^1.0.0" "1gjjn08y5s43p7aizif24i2yvkd1sasy77dix62irkwzig3favqr") | |
|
26 | (fetchbower "iron-form-element-behavior" "PolymerElements/iron-form-element-behavior#1.0.7" "PolymerElements/iron-form-element-behavior#^1.0.0" "02qbxqsqxjzy086cqbv6pgibmi0888q757p95ig6x3nc62xk81an") | |
|
27 | (fetchbower "iron-a11y-keys-behavior" "PolymerElements/iron-a11y-keys-behavior#1.1.9" "PolymerElements/iron-a11y-keys-behavior#^1.0.0" "0dy1ca1nb9v9y968q998vgs147fkmn4irnnrdfl40ln1bln45qx9") | |
|
28 | (fetchbower "paper-ripple" "PolymerElements/paper-ripple#1.0.10" "PolymerElements/paper-ripple#^1.0.0" "0d5gjf7cw7hk520h6xnav1xrpd948qc8mzvqgqycqkad4j4vdck7") | |
|
29 | (fetchbower "font-roboto" "PolymerElements/font-roboto#1.1.0" "PolymerElements/font-roboto#^1.0.1" "0z4msvaa5pnr84j2r957g313fmdbdbrknhdw1axy5g48845yv04s") | |
|
30 | (fetchbower "iron-meta" "PolymerElements/iron-meta#1.1.3" "PolymerElements/iron-meta#^1.0.0" "13lsj648ibkyw3lha6g6r7afmk4yxvgdi63bkpy54wx63gfx7xir") | |
|
31 | (fetchbower "iron-resizable-behavior" "PolymerElements/iron-resizable-behavior#1.0.6" "PolymerElements/iron-resizable-behavior#^1.0.0" "1r8qk670nigqpw50x1m5yvbx7p9sahiwlf0f9z71v508d63vrbi1") | |
|
32 | (fetchbower "iron-selector" "PolymerElements/iron-selector#1.5.3" "PolymerElements/iron-selector#^1.0.0" "1362pq6vy113h4y6hn31hhp52hh8g269s5aj7vsq266v7y59igf6") | |
|
33 | (fetchbower "web-animations-js" "web-animations/web-animations-js#2.3.1" "web-animations/web-animations-js#^2.2.0" "16haz886711qrcf9h9wrjwf5hrz2c69l4jxlq0iyzar823c51qkq") | |
|
33 | 34 | ]; } |
@@ -1,12 +1,14 | |||
|
1 |
# This file has been generated by node2nix 1. |
|
|
1 | # This file has been generated by node2nix 1.5.3. Do not edit! | |
|
2 | 2 | |
|
3 | 3 | {pkgs ? import <nixpkgs> { |
|
4 | 4 | inherit system; |
|
5 | }, system ? builtins.currentSystem}: | |
|
5 | }, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-6_x"}: | |
|
6 | 6 | |
|
7 | 7 | let |
|
8 | 8 | nodeEnv = import ./node-env.nix { |
|
9 |
inherit (pkgs) stdenv python utillinux runCommand writeTextFile |
|
|
9 | inherit (pkgs) stdenv python2 utillinux runCommand writeTextFile; | |
|
10 | inherit nodejs; | |
|
11 | libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null; | |
|
10 | 12 | }; |
|
11 | 13 | in |
|
12 | 14 | import ./node-packages.nix { |
@@ -1,24 +1,26 | |||
|
1 | 1 | # This file originates from node2nix |
|
2 | 2 | |
|
3 |
{stdenv, |
|
|
3 | {stdenv, nodejs, python2, utillinux, libtool, runCommand, writeTextFile}: | |
|
4 | 4 | |
|
5 | 5 | let |
|
6 | python = if nodejs ? python then nodejs.python else python2; | |
|
7 | ||
|
6 | 8 | # Create a tar wrapper that filters all the 'Ignoring unknown extended header keyword' noise |
|
7 | 9 | tarWrapper = runCommand "tarWrapper" {} '' |
|
8 | 10 | mkdir -p $out/bin |
|
9 | ||
|
11 | ||
|
10 | 12 | cat > $out/bin/tar <<EOF |
|
11 | 13 | #! ${stdenv.shell} -e |
|
12 | 14 | $(type -p tar) "\$@" --warning=no-unknown-keyword |
|
13 | 15 | EOF |
|
14 | ||
|
16 | ||
|
15 | 17 | chmod +x $out/bin/tar |
|
16 | 18 | ''; |
|
17 | ||
|
19 | ||
|
18 | 20 | # Function that generates a TGZ file from a NPM project |
|
19 | 21 | buildNodeSourceDist = |
|
20 | 22 | { name, version, src, ... }: |
|
21 | ||
|
23 | ||
|
22 | 24 | stdenv.mkDerivation { |
|
23 | 25 | name = "node-tarball-${name}-${version}"; |
|
24 | 26 | inherit src; |
@@ -42,151 +44,311 let | |||
|
42 | 44 | # Bundle the dependencies of the package |
|
43 | 45 | mkdir -p node_modules |
|
44 | 46 | cd node_modules |
|
45 | ||
|
47 | ||
|
46 | 48 | # Only include dependencies if they don't exist. They may also be bundled in the package. |
|
47 | 49 | if [ ! -e "${dependency.name}" ] |
|
48 | 50 | then |
|
49 | 51 | ${composePackage dependency} |
|
50 | 52 | fi |
|
51 | ||
|
53 | ||
|
52 | 54 | cd .. |
|
53 | 55 | '' |
|
54 | 56 | ) dependencies); |
|
55 | 57 | |
|
56 | 58 | # Recursively composes the dependencies of a package |
|
57 | 59 | composePackage = { name, packageName, src, dependencies ? [], ... }@args: |
|
58 | let | |
|
59 | fixImpureDependencies = writeTextFile { | |
|
60 | name = "fixDependencies.js"; | |
|
61 | text = '' | |
|
62 | var fs = require('fs'); | |
|
63 | var url = require('url'); | |
|
64 | ||
|
65 | /* | |
|
66 | * Replaces an impure version specification by * | |
|
67 | */ | |
|
68 | function replaceImpureVersionSpec(versionSpec) { | |
|
69 | var parsedUrl = url.parse(versionSpec); | |
|
70 | ||
|
71 | if(versionSpec == "latest" || versionSpec == "unstable" || | |
|
72 | versionSpec.substr(0, 2) == ".." || dependency.substr(0, 2) == "./" || dependency.substr(0, 2) == "~/" || dependency.substr(0, 1) == '/') | |
|
73 | return '*'; | |
|
74 | else if(parsedUrl.protocol == "git:" || parsedUrl.protocol == "git+ssh:" || parsedUrl.protocol == "git+http:" || parsedUrl.protocol == "git+https:" || | |
|
75 | parsedUrl.protocol == "http:" || parsedUrl.protocol == "https:") | |
|
76 | return '*'; | |
|
77 | else | |
|
78 | return versionSpec; | |
|
79 | } | |
|
80 | ||
|
81 | var packageObj = JSON.parse(fs.readFileSync('./package.json')); | |
|
82 | ||
|
83 | /* Replace dependencies */ | |
|
84 | if(packageObj.dependencies !== undefined) { | |
|
85 | for(var dependency in packageObj.dependencies) { | |
|
86 | var versionSpec = packageObj.dependencies[dependency]; | |
|
87 | packageObj.dependencies[dependency] = replaceImpureVersionSpec(versionSpec); | |
|
88 | } | |
|
89 | } | |
|
90 | ||
|
91 | /* Replace development dependencies */ | |
|
92 | if(packageObj.devDependencies !== undefined) { | |
|
93 | for(var dependency in packageObj.devDependencies) { | |
|
94 | var versionSpec = packageObj.devDependencies[dependency]; | |
|
95 | packageObj.devDependencies[dependency] = replaceImpureVersionSpec(versionSpec); | |
|
96 | } | |
|
97 | } | |
|
98 | ||
|
99 | /* Replace optional dependencies */ | |
|
100 | if(packageObj.optionalDependencies !== undefined) { | |
|
101 | for(var dependency in packageObj.optionalDependencies) { | |
|
102 | var versionSpec = packageObj.optionalDependencies[dependency]; | |
|
103 | packageObj.optionalDependencies[dependency] = replaceImpureVersionSpec(versionSpec); | |
|
104 | } | |
|
105 | } | |
|
106 | ||
|
107 | /* Write the fixed JSON file */ | |
|
108 | fs.writeFileSync("package.json", JSON.stringify(packageObj)); | |
|
109 | ''; | |
|
110 | }; | |
|
111 | in | |
|
112 | 60 |
'' |
|
113 | 61 | DIR=$(pwd) |
|
114 | 62 | cd $TMPDIR |
|
115 | ||
|
63 | ||
|
116 | 64 | unpackFile ${src} |
|
117 | ||
|
65 | ||
|
118 | 66 | # Make the base dir in which the target dependency resides first |
|
119 | 67 | mkdir -p "$(dirname "$DIR/${packageName}")" |
|
120 | 68 | |
|
121 | 69 | if [ -f "${src}" ] |
|
122 | 70 | then |
|
123 | 71 | # Figure out what directory has been unpacked |
|
124 |
packageDir=$(find . |
|
|
125 | ||
|
72 | packageDir="$(find . -maxdepth 1 -type d | tail -1)" | |
|
73 | ||
|
126 | 74 | # Restore write permissions to make building work |
|
75 | find "$packageDir" -type d -print0 | xargs -0 chmod u+x | |
|
127 | 76 | chmod -R u+w "$packageDir" |
|
128 | ||
|
77 | ||
|
129 | 78 | # Move the extracted tarball into the output folder |
|
130 | 79 | mv "$packageDir" "$DIR/${packageName}" |
|
131 | 80 | elif [ -d "${src}" ] |
|
132 | 81 | then |
|
82 | # Get a stripped name (without hash) of the source directory. | |
|
83 | # On old nixpkgs it's already set internally. | |
|
84 | if [ -z "$strippedName" ] | |
|
85 | then | |
|
86 | strippedName="$(stripHash ${src})" | |
|
87 | fi | |
|
88 | ||
|
133 | 89 | # Restore write permissions to make building work |
|
134 |
|
|
|
135 | ||
|
136 |
|
|
|
137 |
|
|
|
90 | chmod -R u+w "$strippedName" | |
|
91 | ||
|
92 | # Move the extracted directory into the output folder | |
|
93 | mv "$strippedName" "$DIR/${packageName}" | |
|
138 | 94 | fi |
|
139 | ||
|
95 | ||
|
140 | 96 | # Unset the stripped name to not confuse the next unpack step |
|
141 | 97 | unset strippedName |
|
142 | ||
|
143 | # Some version specifiers (latest, unstable, URLs, file paths) force NPM to make remote connections or consult paths outside the Nix store. | |
|
144 | # The following JavaScript replaces these by * to prevent that | |
|
98 | ||
|
99 | # Include the dependencies of the package | |
|
145 | 100 | cd "$DIR/${packageName}" |
|
146 | node ${fixImpureDependencies} | |
|
147 | ||
|
148 | # Include the dependencies of the package | |
|
149 | 101 | ${includeDependencies { inherit dependencies; }} |
|
150 | 102 | cd .. |
|
151 | 103 | ${stdenv.lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} |
|
152 | 104 | ''; |
|
153 | 105 | |
|
106 | pinpointDependencies = {dependencies, production}: | |
|
107 | let | |
|
108 | pinpointDependenciesFromPackageJSON = writeTextFile { | |
|
109 | name = "pinpointDependencies.js"; | |
|
110 | text = '' | |
|
111 | var fs = require('fs'); | |
|
112 | var path = require('path'); | |
|
113 | ||
|
114 | function resolveDependencyVersion(location, name) { | |
|
115 | if(location == process.env['NIX_STORE']) { | |
|
116 | return null; | |
|
117 | } else { | |
|
118 | var dependencyPackageJSON = path.join(location, "node_modules", name, "package.json"); | |
|
119 | ||
|
120 | if(fs.existsSync(dependencyPackageJSON)) { | |
|
121 | var dependencyPackageObj = JSON.parse(fs.readFileSync(dependencyPackageJSON)); | |
|
122 | ||
|
123 | if(dependencyPackageObj.name == name) { | |
|
124 | return dependencyPackageObj.version; | |
|
125 | } | |
|
126 | } else { | |
|
127 | return resolveDependencyVersion(path.resolve(location, ".."), name); | |
|
128 | } | |
|
129 | } | |
|
130 | } | |
|
131 | ||
|
132 | function replaceDependencies(dependencies) { | |
|
133 | if(typeof dependencies == "object" && dependencies !== null) { | |
|
134 | for(var dependency in dependencies) { | |
|
135 | var resolvedVersion = resolveDependencyVersion(process.cwd(), dependency); | |
|
136 | ||
|
137 | if(resolvedVersion === null) { | |
|
138 | process.stderr.write("WARNING: cannot pinpoint dependency: "+dependency+", context: "+process.cwd()+"\n"); | |
|
139 | } else { | |
|
140 | dependencies[dependency] = resolvedVersion; | |
|
141 | } | |
|
142 | } | |
|
143 | } | |
|
144 | } | |
|
145 | ||
|
146 | /* Read the package.json configuration */ | |
|
147 | var packageObj = JSON.parse(fs.readFileSync('./package.json')); | |
|
148 | ||
|
149 | /* Pinpoint all dependencies */ | |
|
150 | replaceDependencies(packageObj.dependencies); | |
|
151 | if(process.argv[2] == "development") { | |
|
152 | replaceDependencies(packageObj.devDependencies); | |
|
153 | } | |
|
154 | replaceDependencies(packageObj.optionalDependencies); | |
|
155 | ||
|
156 | /* Write the fixed package.json file */ | |
|
157 | fs.writeFileSync("package.json", JSON.stringify(packageObj, null, 2)); | |
|
158 | ''; | |
|
159 | }; | |
|
160 | in | |
|
161 | '' | |
|
162 | node ${pinpointDependenciesFromPackageJSON} ${if production then "production" else "development"} | |
|
163 | ||
|
164 | ${stdenv.lib.optionalString (dependencies != []) | |
|
165 | '' | |
|
166 | if [ -d node_modules ] | |
|
167 | then | |
|
168 | cd node_modules | |
|
169 | ${stdenv.lib.concatMapStrings (dependency: pinpointDependenciesOfPackage dependency) dependencies} | |
|
170 | cd .. | |
|
171 | fi | |
|
172 | ''} | |
|
173 | ''; | |
|
174 | ||
|
175 | # Recursively traverses all dependencies of a package and pinpoints all | |
|
176 | # dependencies in the package.json file to the versions that are actually | |
|
177 | # being used. | |
|
178 | ||
|
179 | pinpointDependenciesOfPackage = { packageName, dependencies ? [], production ? true, ... }@args: | |
|
180 | '' | |
|
181 | if [ -d "${packageName}" ] | |
|
182 | then | |
|
183 | cd "${packageName}" | |
|
184 | ${pinpointDependencies { inherit dependencies production; }} | |
|
185 | cd .. | |
|
186 | ${stdenv.lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} | |
|
187 | fi | |
|
188 | ''; | |
|
189 | ||
|
154 | 190 | # Extract the Node.js source code which is used to compile packages with |
|
155 | 191 | # native bindings |
|
156 | 192 | nodeSources = runCommand "node-sources" {} '' |
|
157 | 193 | tar --no-same-owner --no-same-permissions -xf ${nodejs.src} |
|
158 | 194 | mv node-* $out |
|
159 | 195 | ''; |
|
160 | ||
|
196 | ||
|
197 | # Script that adds _integrity fields to all package.json files to prevent NPM from consulting the cache (that is empty) | |
|
198 | addIntegrityFieldsScript = writeTextFile { | |
|
199 | name = "addintegrityfields.js"; | |
|
200 | text = '' | |
|
201 | var fs = require('fs'); | |
|
202 | var path = require('path'); | |
|
203 | ||
|
204 | function augmentDependencies(baseDir, dependencies) { | |
|
205 | for(var dependencyName in dependencies) { | |
|
206 | var dependency = dependencies[dependencyName]; | |
|
207 | ||
|
208 | // Open package.json and augment metadata fields | |
|
209 | var packageJSONDir = path.join(baseDir, "node_modules", dependencyName); | |
|
210 | var packageJSONPath = path.join(packageJSONDir, "package.json"); | |
|
211 | ||
|
212 | if(fs.existsSync(packageJSONPath)) { // Only augment packages that exist. Sometimes we may have production installs in which development dependencies can be ignored | |
|
213 | console.log("Adding metadata fields to: "+packageJSONPath); | |
|
214 | var packageObj = JSON.parse(fs.readFileSync(packageJSONPath)); | |
|
215 | ||
|
216 | if(dependency.integrity) { | |
|
217 | packageObj["_integrity"] = dependency.integrity; | |
|
218 | } else { | |
|
219 | packageObj["_integrity"] = "sha1-000000000000000000000000000="; // When no _integrity string has been provided (e.g. by Git dependencies), add a dummy one. It does not seem to harm and it bypasses downloads. | |
|
220 | } | |
|
221 | ||
|
222 | packageObj["_resolved"] = dependency.version; // Set the resolved version to the version identifier. This prevents NPM from cloning Git repositories. | |
|
223 | fs.writeFileSync(packageJSONPath, JSON.stringify(packageObj, null, 2)); | |
|
224 | } | |
|
225 | ||
|
226 | // Augment transitive dependencies | |
|
227 | if(dependency.dependencies !== undefined) { | |
|
228 | augmentDependencies(packageJSONDir, dependency.dependencies); | |
|
229 | } | |
|
230 | } | |
|
231 | } | |
|
232 | ||
|
233 | if(fs.existsSync("./package-lock.json")) { | |
|
234 | var packageLock = JSON.parse(fs.readFileSync("./package-lock.json")); | |
|
235 | ||
|
236 | if(packageLock.lockfileVersion !== 1) { | |
|
237 | process.stderr.write("Sorry, I only understand lock file version 1!\n"); | |
|
238 | process.exit(1); | |
|
239 | } | |
|
240 | ||
|
241 | if(packageLock.dependencies !== undefined) { | |
|
242 | augmentDependencies(".", packageLock.dependencies); | |
|
243 | } | |
|
244 | } | |
|
245 | ''; | |
|
246 | }; | |
|
247 | ||
|
248 | # Reconstructs a package-lock file from the node_modules/ folder structure and package.json files with dummy sha1 hashes | |
|
249 | reconstructPackageLock = writeTextFile { | |
|
250 | name = "addintegrityfields.js"; | |
|
251 | text = '' | |
|
252 | var fs = require('fs'); | |
|
253 | var path = require('path'); | |
|
254 | ||
|
255 | var packageObj = JSON.parse(fs.readFileSync("package.json")); | |
|
256 | ||
|
257 | var lockObj = { | |
|
258 | name: packageObj.name, | |
|
259 | version: packageObj.version, | |
|
260 | lockfileVersion: 1, | |
|
261 | requires: true, | |
|
262 | dependencies: {} | |
|
263 | }; | |
|
264 | ||
|
265 | function augmentPackageJSON(filePath, dependencies) { | |
|
266 | var packageJSON = path.join(filePath, "package.json"); | |
|
267 | if(fs.existsSync(packageJSON)) { | |
|
268 | var packageObj = JSON.parse(fs.readFileSync(packageJSON)); | |
|
269 | dependencies[packageObj.name] = { | |
|
270 | version: packageObj.version, | |
|
271 | integrity: "sha1-000000000000000000000000000=", | |
|
272 | dependencies: {} | |
|
273 | }; | |
|
274 | processDependencies(path.join(filePath, "node_modules"), dependencies[packageObj.name].dependencies); | |
|
275 | } | |
|
276 | } | |
|
277 | ||
|
278 | function processDependencies(dir, dependencies) { | |
|
279 | if(fs.existsSync(dir)) { | |
|
280 | var files = fs.readdirSync(dir); | |
|
281 | ||
|
282 | files.forEach(function(entry) { | |
|
283 | var filePath = path.join(dir, entry); | |
|
284 | var stats = fs.statSync(filePath); | |
|
285 | ||
|
286 | if(stats.isDirectory()) { | |
|
287 | if(entry.substr(0, 1) == "@") { | |
|
288 | // When we encounter a namespace folder, augment all packages belonging to the scope | |
|
289 | var pkgFiles = fs.readdirSync(filePath); | |
|
290 | ||
|
291 | pkgFiles.forEach(function(entry) { | |
|
292 | if(stats.isDirectory()) { | |
|
293 | var pkgFilePath = path.join(filePath, entry); | |
|
294 | augmentPackageJSON(pkgFilePath, dependencies); | |
|
295 | } | |
|
296 | }); | |
|
297 | } else { | |
|
298 | augmentPackageJSON(filePath, dependencies); | |
|
299 | } | |
|
300 | } | |
|
301 | }); | |
|
302 | } | |
|
303 | } | |
|
304 | ||
|
305 | processDependencies("node_modules", lockObj.dependencies); | |
|
306 | ||
|
307 | fs.writeFileSync("package-lock.json", JSON.stringify(lockObj, null, 2)); | |
|
308 | ''; | |
|
309 | }; | |
|
310 | ||
|
161 | 311 | # Builds and composes an NPM package including all its dependencies |
|
162 | buildNodePackage = { name, packageName, version, dependencies ? [], production ? true, npmFlags ? "", dontNpmInstall ? false, preRebuild ? "", ... }@args: | |
|
163 | ||
|
312 | buildNodePackage = { name, packageName, version, dependencies ? [], production ? true, npmFlags ? "", dontNpmInstall ? false, bypassCache ? false, preRebuild ? "", ... }@args: | |
|
313 | ||
|
314 | let | |
|
315 | forceOfflineFlag = if bypassCache then "--offline" else "--registry http://www.example.com"; | |
|
316 | in | |
|
164 | 317 | stdenv.lib.makeOverridable stdenv.mkDerivation (builtins.removeAttrs args [ "dependencies" ] // { |
|
165 | 318 | name = "node-${name}-${version}"; |
|
166 | buildInputs = [ tarWrapper python nodejs ] ++ stdenv.lib.optional (stdenv.isLinux) utillinux ++ args.buildInputs or []; | |
|
319 | buildInputs = [ tarWrapper python nodejs ] | |
|
320 | ++ stdenv.lib.optional (stdenv.isLinux) utillinux | |
|
321 | ++ stdenv.lib.optional (stdenv.isDarwin) libtool | |
|
322 | ++ args.buildInputs or []; | |
|
167 | 323 | dontStrip = args.dontStrip or true; # Striping may fail a build for some package deployments |
|
168 | ||
|
324 | ||
|
169 | 325 | inherit dontNpmInstall preRebuild; |
|
170 | ||
|
326 | ||
|
171 | 327 | unpackPhase = args.unpackPhase or "true"; |
|
172 | ||
|
328 | ||
|
173 | 329 | buildPhase = args.buildPhase or "true"; |
|
174 | ||
|
330 | ||
|
175 | 331 | compositionScript = composePackage args; |
|
176 | passAsFile = [ "compositionScript" ]; | |
|
177 | ||
|
332 | pinpointDependenciesScript = pinpointDependenciesOfPackage args; | |
|
333 | ||
|
334 | passAsFile = [ "compositionScript" "pinpointDependenciesScript" ]; | |
|
335 | ||
|
178 | 336 | installPhase = args.installPhase or '' |
|
179 | 337 | # Create and enter a root node_modules/ folder |
|
180 | 338 | mkdir -p $out/lib/node_modules |
|
181 | 339 | cd $out/lib/node_modules |
|
182 | ||
|
340 | ||
|
183 | 341 | # Compose the package and all its dependencies |
|
184 | 342 | source $compositionScriptPath |
|
185 | ||
|
343 | ||
|
344 | # Pinpoint the versions of all dependencies to the ones that are actually being used | |
|
345 | echo "pinpointing versions of dependencies..." | |
|
346 | source $pinpointDependenciesScriptPath | |
|
347 | ||
|
186 | 348 | # Patch the shebangs of the bundled modules to prevent them from |
|
187 | 349 | # calling executables outside the Nix store as much as possible |
|
188 | 350 | patchShebangs . |
|
189 | ||
|
351 | ||
|
190 | 352 | # Deploy the Node.js package by running npm install. Since the |
|
191 | 353 | # dependencies have been provided already by ourselves, it should not |
|
192 | 354 | # attempt to install them again, which is good, because we want to make |
@@ -196,23 +358,37 let | |||
|
196 | 358 | # |
|
197 | 359 | # The other responsibilities of NPM are kept -- version checks, build |
|
198 | 360 | # steps, postprocessing etc. |
|
199 | ||
|
361 | ||
|
200 | 362 | export HOME=$TMPDIR |
|
201 | 363 | cd "${packageName}" |
|
202 | 364 | runHook preRebuild |
|
203 | npm --registry http://www.example.com --nodedir=${nodeSources} ${npmFlags} ${stdenv.lib.optionalString production "--production"} rebuild | |
|
204 | ||
|
365 | ||
|
366 | ${stdenv.lib.optionalString bypassCache '' | |
|
367 | if [ ! -f package-lock.json ] | |
|
368 | then | |
|
369 | echo "No package-lock.json file found, reconstructing..." | |
|
370 | node ${reconstructPackageLock} | |
|
371 | fi | |
|