Merge 'staging' into closure-size

- there were many easy merge conflicts
- cc-wrapper needed nontrivial changes

Many other problems might've been created by interaction of the branches,
but stdenv and a few other packages build fine now.
This commit is contained in:
Vladimír Čunát 2015-04-18 11:00:58 +02:00
commit bf414c9d4f
6303 changed files with 375447 additions and 91361 deletions

7
.gitignore vendored
View File

@ -10,4 +10,9 @@ result-*
/doc/manual.pdf /doc/manual.pdf
.version-suffix .version-suffix
.DS_Store .DS_Store
/pkgs/applications/kde-apps-*/tmp/
/pkgs/development/libraries/kde-frameworks-*/tmp/
/pkgs/development/libraries/qt-5/*/tmp/
/pkgs/desktops/plasma-*/tmp/

6
.travis.yml Normal file
View File

@ -0,0 +1,6 @@
language: python
python: "3.4"
sudo: required
before_install: ./maintainers/scripts/travis-nox-review-pr.sh nix
install: ./maintainers/scripts/travis-nox-review-pr.sh nox
script: ./maintainers/scripts/travis-nox-review-pr.sh build

View File

@ -1 +1 @@
14.10 15.05

View File

@ -1,10 +1,26 @@
Nixpkgs is a collection of packages for [Nix](http://nixos.org/nix/) package [<img src="http://nixos.org/logo/nixos-hires.png" width="500px" alt="logo" />
manager. Nixpkgs also includes [NixOS](http://nixos.org/nixos/) linux distribution source code. ](https://nixos.org/nixos)
[![Build Status](https://travis-ci.org/NixOS/nixpkgs.svg?branch=master)](https://travis-ci.org/NixOS/nixpkgs) [![Issue Stats](http://www.issuestats.com/github/nixos/nixpkgs/badge/pr)](http://www.issuestats.com/github/nixos/nixpkgs) [![Issue Stats](http://www.issuestats.com/github/nixos/nixpkgs/badge/issue)](http://www.issuestats.com/github/nixos/nixpkgs)
Nixpkgs is a collection of packages for [Nix](https://nixos.org/nix/) package
manager.
[NixOS](https://nixos.org/nixos/) linux distribution source code is located inside `nixos/` folder.
* [NixOS installation instructions](https://nixos.org/nixos/manual/#ch-installation)
* [Documentation (Nix Expression Language chapter)](https://nixos.org/nix/manual/#ch-expression-language)
* [Manual (How to write packages for Nix)](https://nixos.org/nixpkgs/manual/)
* [Manual (NixOS)](https://nixos.org/nixos/manual/)
* [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined)
* [Continuous package builds for 14.12 release](https://hydra.nixos.org/jobset/nixos/release-14.12)
* [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
* [Tests for 14.12 release](https://hydra.nixos.org/job/nixos/release-14.12/tested#tabs-constituents)
Communication:
* [NixOS installation instructions](http://nixos.org/nixos/manual/#ch-installation)
* [Manual (How to write packages for Nix)](http://nixos.org/nixpkgs/manual/)
* [Manual (NixOS)](http://nixos.org/nixos/manual/)
* [Continuous build](http://hydra.nixos.org/jobset/nixos/trunk-combined)
* [Tests](http://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
* [Mailing list](http://lists.science.uu.nl/mailman/listinfo/nix-dev) * [Mailing list](http://lists.science.uu.nl/mailman/listinfo/nix-dev)
* [IRC - #nixos on freenode.net](irc://irc.freenode.net/#nixos) * [IRC - #nixos on freenode.net](irc://irc.freenode.net/#nixos)
---
[![Throughput Graph](https://graphs.waffle.io/nixos/nixpkgs/throughput.svg)](https://waffle.io/nixos/nixpkgs/metrics)

View File

@ -1,6 +1,6 @@
if ! builtins ? nixVersion || builtins.compareVersions "1.6" builtins.nixVersion == 1 then if ! builtins ? nixVersion || builtins.compareVersions "1.8" builtins.nixVersion == 1 then
abort "This version of Nixpkgs requires Nix >= 1.6, please upgrade!" abort "This version of Nixpkgs requires Nix >= 1.8, please upgrade! See https://nixos.org/wiki/How_to_update_when_nix_is_too_old_to_evaluate_nixpkgs"
else else

View File

@ -10,9 +10,7 @@
<listitem><para><command>$ git clone git://github.com/NixOS/nixpkgs.git</command></para></listitem> <listitem><para><command>$ git clone git://github.com/NixOS/nixpkgs.git</command></para></listitem>
<listitem><para><command>$ cd nixpkgs/pkgs/top-level</command></para></listitem> <listitem><para><command>$ nix-build -A manual nixpkgs/pkgs/top-level/release.nix</command></para></listitem>
<listitem><para><command>$ nix-build -A tarball release.nix</command></para></listitem>
<listitem><para>Inside the built derivation you shall see <literal>manual/index.html</literal> file.</para></listitem> <listitem><para>Inside the built derivation you shall see <literal>manual/index.html</literal> file.</para></listitem>

View File

@ -108,7 +108,7 @@ a <varname>preConfigure</varname> hook to generate a configuration
file used by <filename>Makefile.PL</filename>: file used by <filename>Makefile.PL</filename>:
<programlisting> <programlisting>
{buildPerlPackage, fetchurl, db}: { buildPerlPackage, fetchurl, db }:
buildPerlPackage rec { buildPerlPackage rec {
name = "BerkeleyDB-0.36"; name = "BerkeleyDB-0.36";
@ -191,45 +191,548 @@ you need it.</para>
</section> </section>
<section><title>Python</title> <section xml:id="python"><title>Python</title>
<para> <para>
Python packages that Currently supported interpreters are <varname>python26</varname>, <varname>python27</varname>,
use <link xlink:href="http://pypi.python.org/pypi/setuptools/"><literal>setuptools</literal></link>, <varname>python32</varname>, <varname>python33</varname>, <varname>python34</varname>
which many Python packages do nowadays, can be built very simply using and <varname>pypy</varname>.
the <varname>buildPythonPackage</varname> function. This function is
implemented
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/generic/default.nix"><filename>pkgs/development/python-modules/generic/default.nix</filename></link>
and works similarly to <varname>buildPerlPackage</varname>. (See
<xref linkend="ssec-language-perl"/> for details.)
</para> </para>
<para> <para>
Python packages that use <varname>buildPythonPackage</varname> are <varname>python</varname> is an alias of <varname>python27</varname> and <varname>python3</varname> is an alias of <varname>python34</varname>.
defined </para>
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link>.
Most of them are simple. For example:
<programlisting> <para>
<varname>python26</varname> and <varname>python27</varname> do not include modules that require
external dependencies (to reduce dependency bloat). Following modules need to be added as
<varname>buildInput</varname> explicitly:
</para>
<itemizedlist>
<listitem><para><varname>python.modules.bsddb</varname></para></listitem>
<listitem><para><varname>python.modules.curses</varname></para></listitem>
<listitem><para><varname>python.modules.curses_panel</varname></para></listitem>
<listitem><para><varname>python.modules.crypt</varname></para></listitem>
<listitem><para><varname>python.modules.gdbm</varname></para></listitem>
<listitem><para><varname>python.modules.sqlite3</varname></para></listitem>
<listitem><para><varname>python.modules.tkinter</varname></para></listitem>
<listitem><para><varname>python.modules.readline</varname></para></listitem>
</itemizedlist>
<para>For convenience <varname>python27Full</varname> and <varname>python26Full</varname>
are provided with all modules included.</para>
<para>
Python packages that
use <link xlink:href="http://pypi.python.org/pypi/setuptools/"><literal>setuptools</literal></link> or <literal>distutils</literal>,
can be built using the <varname>buildPythonPackage</varname> function as documented below.
</para>
<para>
All packages depending on any Python interpreter get appended <varname>$out/${python.libPrefix}/site-packages</varname>
to <literal>$PYTHONPATH</literal> if such directory exists.
</para>
<variablelist>
<title>
Useful attributes on interpreters packages:
</title>
<varlistentry>
<term><varname>libPrefix</varname></term>
<listitem><para>
Name of the folder in <literal>${python}/lib/</literal> for corresponding interpreter.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>interpreter</varname></term>
<listitem><para>
Alias for <literal>${python}/bin/${executable}.</literal>
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>buildEnv</varname></term>
<listitem><para>
Function to build python interpreter environments with extra packages bundled together.
See <xref linkend="python-build-env" /> for usage and documentation.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>sitePackages</varname></term>
<listitem><para>
Alias for <literal>lib/${libPrefix}/site-packages</literal>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>executable</varname></term>
<listitem><para>
Name of the interpreter executable, ie <literal>python3.4</literal>.
</para></listitem>
</varlistentry>
</variablelist>
<section xml:id="build-python-package"><title><varname>buildPythonPackage</varname> function</title>
<para>
The function is implemented in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/generic/default.nix">
<filename>pkgs/development/python-modules/generic/default.nix</filename></link>.
Example usage:
<programlisting language="nix">
twisted = buildPythonPackage { twisted = buildPythonPackage {
name = "twisted-8.1.0"; name = "twisted-8.1.0";
src = fetchurl { src = pkgs.fetchurl {
url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2; url = http://tmrc.mit.edu/mirror/twisted/Twisted/8.1/Twisted-8.1.0.tar.bz2;
sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl"; sha256 = "0q25zbr4xzknaghha72mq57kh53qw1bf8csgp63pm9sfi72qhirl";
}; };
propagatedBuildInputs = [ pkgs.ZopeInterface ]; propagatedBuildInputs = [ self.ZopeInterface ];
meta = { meta = {
homepage = http://twistedmatrix.com/; homepage = http://twistedmatrix.com/;
description = "Twisted, an event-driven networking engine written in Python"; description = "Twisted, an event-driven networking engine written in Python";
license = "MIT"; license = stdenv.lib.licenses.mit;
}; };
}; };
</programlisting> </programlisting>
Most of Python packages that use <varname>buildPythonPackage</varname> are defined
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link>
and generated for each python interpreter separately into attribute sets <varname>python26Packages</varname>,
<varname>python27Packages</varname>, <varname>python32Packages</varname>, <varname>python33Packages</varname>,
<varname>python34Packages</varname> and <varname>pypyPackages</varname>.
</para>
<para>
<function>buildPythonPackage</function> mainly does four things:
<orderedlist>
<listitem><para>
In the <varname>configurePhase</varname>, it patches
<literal>setup.py</literal> to always include setuptools before
distutils for monkeypatching machinery to take place.
</para></listitem>
<listitem><para>
In the <varname>buildPhase</varname>, it calls
<literal>${python.interpreter} setup.py build ...</literal>
</para></listitem>
<listitem><para>
In the <varname>installPhase</varname>, it calls
<literal>${python.interpreter} setup.py install ...</literal>
</para></listitem>
<listitem><para>
In the <varname>postFixup</varname> phase, <literal>wrapPythonPrograms</literal>
bash function is called to wrap all programs in <filename>$out/bin/*</filename>
directory to include <literal>$PYTHONPATH</literal> and <literal>$PATH</literal>
environment variables.
</para></listitem>
</orderedlist>
</para>
<para>By default <varname>doCheck = true</varname> is set and tests are run with
<literal>${python.interpreter} setup.py test</literal> command in <varname>checkPhase</varname>.</para>
<para><varname>propagatedBuildInputs</varname> packages are propagated to user environment.</para>
<para>
By default <varname>meta.platforms</varname> is set to the same value
as the interpreter unless overriden otherwise.
</para>
<variablelist>
<title>
<varname>buildPythonPackage</varname> parameters
(all parameters from <varname>mkDerivation</varname> function are still supported)
</title>
<varlistentry>
<term><varname>namePrefix</varname></term>
<listitem><para>
Prepended text to <varname>${name}</varname> parameter.
Defaults to <literal>"python3.3-"</literal> for Python 3.3, etc. Set it to
<literal>""</literal>
if you're packaging an application or a command line tool.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>disabled</varname></term>
<listitem><para>
If <varname>true</varname>, package is not build for
particular python interpreter version. Grep around
<filename>pkgs/top-level/python-packages.nix</filename>
for examples.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>setupPyInstallFlags</varname></term>
<listitem><para>
List of flags passed to <command>setup.py install</command> command.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>setupPyBuildFlags</varname></term>
<listitem><para>
List of flags passed to <command>setup.py build</command> command.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>pythonPath</varname></term>
<listitem><para>
List of packages to be added into <literal>$PYTHONPATH</literal>.
Packages in <varname>pythonPath</varname> are not propagated into user environment
(contrary to <varname>propagatedBuildInputs</varname>).
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>preShellHook</varname></term>
<listitem><para>
Hook to execute commands before <varname>shellHook</varname>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>postShellHook</varname></term>
<listitem><para>
Hook to execute commands after <varname>shellHook</varname>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>distutilsExtraCfg</varname></term>
<listitem><para>
Extra lines passed to <varname>[easy_install]</varname> section of
<filename>distutils.cfg</filename> (acts as global setup.cfg
configuration).
</para></listitem>
</varlistentry>
</variablelist>
</section>
<section xml:id="python-build-env"><title><function>python.buildEnv</function> function</title>
<para>
Create Python environments using low-level <function>pkgs.buildEnv</function> function. Example <filename>default.nix</filename>:
<programlisting language="nix">
<![CDATA[with import <nixpkgs> {};
python.buildEnv.override {
extraLibs = [ pkgs.pythonPackages.pyramid ];
ignoreCollisions = true;
}]]>
</programlisting>
Running <command>nix-build</command> will create
<filename>/nix/store/cf1xhjwzmdki7fasgr4kz6di72ykicl5-python-2.7.8-env</filename>
with wrapped binaries in <filename>bin/</filename>.
</para>
<variablelist>
<title>
<function>python.buildEnv</function> arguments
</title>
<varlistentry>
<term><varname>extraLibs</varname></term>
<listitem><para>
List of packages installed inside the environment.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>postBuild</varname></term>
<listitem><para>
Shell command executed after the build of environment.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ignoreCollisions</varname></term>
<listitem><para>
Ignore file collisions inside the environment (default is <varname>false</varname>).
</para></listitem>
</varlistentry>
</variablelist>
</section>
<section xml:id="python-tools"><title>Tools</title>
<para>Packages inside nixpkgs are written by hand. However many tools
exist in community to help save time. No tool is preferred at the moment.
</para> </para>
<itemizedlist>
<listitem><para>
<link xlink:href="https://github.com/proger/python2nix">python2nix</link>
by Vladimir Kirillov
</para></listitem>
<listitem><para>
<link xlink:href="https://github.com/garbas/pypi2nix">pypi2nix</link>
by Rok Garbas
</para></listitem>
<listitem><para>
<link xlink:href="https://github.com/offlinehacker/pypi2nix">pypi2nix</link>
by Jaka Hudoklin
</para></listitem>
</itemizedlist>
</section>
<section xml:id="python-development"><title>Development</title>
<para>
To develop Python packages <function>buildPythonPackage</function> has
additional logic inside <varname>shellPhase</varname> to run
<command>${python.interpreter} setup.py develop</command> for the package.
</para>
<warning><para><varname>shellPhase</varname> is executed only if <filename>setup.py</filename>
exists.</para></warning>
<para>
Given a <filename>default.nix</filename>:
<programlisting language="nix">
<![CDATA[with import <nixpkgs> {};
buildPythonPackage {
name = "myproject";
buildInputs = with pkgs.pythonPackages; [ pyramid ];
src = ./.;
}]]>
</programlisting>
Running <command>nix-shell</command> with no arguments should give you
the environment in which the package would be build with
<command>nix-build</command>.
</para>
<para>
Shortcut to setup environments with C headers/libraries and python packages:
<programlisting language="bash">$ nix-shell -p pythonPackages.pyramid zlib libjpeg git</programlisting>
</para>
<note><para>
There is a boolean value <varname>lib.inNixShell</varname> set to
<varname>true</varname> if nix-shell is invoked.
</para></note>
</section>
<section xml:id="python-faq"><title>FAQ</title>
<variablelist>
<varlistentry>
<term>How to solve circular dependencies?</term>
<listitem><para>
If you have packages <varname>A</varname> and <varname>B</varname> that
depend on each other, when packaging <varname>B</varname> override package
<varname>A</varname> not to depend on <varname>B</varname> as input
(and also the other way around).
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>install_data / data_files</varname> problems resulting into <literal>error: could not create '/nix/store/6l1bvljpy8gazlsw2aw9skwwp4pmvyxw-python-2.7.8/etc': Permission denied</literal></term>
<listitem><para>
<link xlink:href="https://bitbucket.org/pypa/setuptools/issue/130/install_data-doesnt-respect-prefix">
Known bug in setuptools <varname>install_data</varname> does not respect --prefix</link>. Example of
such package using the feature is <filename>pkgs/tools/X11/xpra/default.nix</filename>. As workaround
install it as an extra <varname>preInstall</varname> step:
<programlisting>${python.interpreter} setup.py install_data --install-dir=$out --root=$out
sed -i '/ = data_files/d' setup.py</programlisting>
</para></listitem>
</varlistentry>
<varlistentry>
<term>Rationale of non-existent global site-packages</term>
<listitem><para>
There is no need to have global site-packages in Nix. Each package has isolated
dependency tree and installing any python package will only populate <varname>$PATH</varname>
inside user environment. See <xref linkend="python-build-env" /> to create self-contained
interpreter with a set of packages.
</para></listitem>
</varlistentry>
</variablelist>
</section>
<section xml:id="python-contrib"><title>Contributing guidelines</title>
<para>
Following rules are desired to be respected:
</para>
<itemizedlist>
<listitem><para>
Make sure package builds for all python interpreters. Use <varname>disabled</varname> argument to
<function>buildPythonPackage</function> to set unsupported interpreters.
</para></listitem>
<listitem><para>
If tests need to be disabled for a package, make sure you leave a comment about reasoning.
</para></listitem>
<listitem><para>
Packages in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/python-packages.nix"><filename>pkgs/top-level/python-packages.nix</filename></link>
are sorted quasi-alphabetically to avoid merge conflicts.
</para></listitem>
</itemizedlist>
</section>
</section>
<section xml:id="ssec-language-ruby"><title>Ruby</title>
<para>There currently is support to bundle applications that are packaged as Ruby gems. The utility "bundix" allows you to write a <filename>Gemfile</filename>, let bundler create a <filename>Gemfile.lock</filename>, and then convert
this into a nix expression that contains all Gem dependencies automatically.</para>
<para>For example, to package sensu, we did:</para>
<screen>
<![CDATA[$ cd pkgs/servers/monitoring
$ mkdir sensu
$ cat > Gemfile
source 'https://rubygems.org'
gem 'sensu'
$ bundler package --path /tmp/vendor/bundle
$ $(nix-build '&nixpkgs>' -A bundix)/bin/bundix
$ cat > default.nix
{ lib, bundlerEnv, ruby }:
bundlerEnv {
name = "sensu-0.17.1";
inherit ruby;
gemfile = ./Gemfile;
lockfile = ./Gemfile.lock;
gemset = ./gemset.nix;
meta = with lib; {
description = "A monitoring framework that aims to be simple, malleable,
and scalable.";
homepage = http://sensuapp.org/;
license = with licenses; mit;
maintainers = with maintainers; [ theuni ];
platforms = platforms.unix;
};
}]]>
</screen>
<para>Please check in the <filename>Gemfile</filename>, <filename>Gemfile.lock</filename> and the <filename>gemset.nix</filename> so future updates can be run easily.
</para>
</section>
<section xml:id="ssec-language-go"><title>Go</title>
<para>The function <varname>buildGoPackage</varname> builds
standard Go packages.
</para>
<example xml:id='ex-buildGoPackage'><title>buildGoPackage</title>
<programlisting>
net = buildGoPackage rec {
name = "go.net-${rev}";
goPackagePath = "code.google.com/p/go.net"; <co xml:id='ex-buildGoPackage-1' />
subPackages = [ "ipv4" "ipv6" ]; <co xml:id='ex-buildGoPackage-2' />
rev = "28ff664507e4";
src = fetchhg {
inherit rev;
url = "https://${goPackagePath}";
sha256 = "1lkz4c9pyz3yz2yz18hiycvlfhgy3jxp68bs7mv7bcfpaj729qav";
};
propagatedBuildInputs = [ goPackages.text ]; <co xml:id='ex-buildGoPackage-3' />
};
</programlisting>
</example>
<para><xref linkend='ex-buildGoPackage'/> is an example expression using buildGoPackage,
the following arguments are of special significance to the function:
<calloutlist>
<callout arearefs='ex-buildGoPackage-1'>
<para>
<varname>goPackagePath</varname> specifies the package's canonical Go import path.
</para>
</callout>
<callout arearefs='ex-buildGoPackage-2'>
<para>
<varname>subPackages</varname> limits the builder from building child packages that
have not been listed. If <varname>subPackages</varname> is not specified, all child
packages will be built.
</para>
<para>
In this example only <literal>code.google.com/p/go.net/ipv4</literal> and
<literal>code.google.com/p/go.net/ipv4</literal> will be built.
</para>
</callout>
<callout arearefs='ex-buildGoPackage-3'>
<para>
<varname>propagatedBuildInputs</varname> is where the dependencies of a Go library are
listed. Only libraries should list <varname>propagatedBuildInputs</varname>. If a standalone
program is being build instead, use <varname>buildInputs</varname>. If a library's tests require
additional dependencies that are not propagated, they should be listed in <varname>buildInputs</varname>.
</para>
</callout>
</calloutlist>
</para>
<para>
Reusable Go libraries may be found in the <varname>goPackages</varname> set. You can test
build a Go package as follows:
<screen>
$ nix-build -A goPackages.net
</screen>
</para>
<para>
You may use Go packages installed into the active Nix profiles by adding
the following to your ~/.bashrc:
<screen>
for p in $NIX_PROFILES; do
GOPATH="$p/share/go:$GOPATH"
done
</screen>
</para>
<para>To extract dependency information from a Go package in automated way use <link xlink:href="https://github.com/cstrahan/go2nix">go2nix</link>.</para>
</section> </section>
@ -314,6 +817,90 @@ Runtime) instead of the OpenJRE.</para>
</section> </section>
<section xml:id="ssec-language-lua"><title>Lua</title>
<para>
Lua packages are built by the <varname>buildLuaPackage</varname> function. This function is
implemented
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/lua-modules/generic/default.nix">
<filename>pkgs/development/lua-modules/generic/default.nix</filename></link>
and works similarly to <varname>buildPerlPackage</varname>. (See
<xref linkend="ssec-language-perl"/> for details.)
</para>
<para>
Lua packages are defined
in <link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/lua-packages.nix"><filename>pkgs/top-level/lua-packages.nix</filename></link>.
Most of them are simple. For example:
<programlisting>
fileSystem = buildLuaPackage {
name = "filesystem-1.6.2";
src = fetchurl {
url = "https://github.com/keplerproject/luafilesystem/archive/v1_6_2.tar.gz";
sha256 = "1n8qdwa20ypbrny99vhkmx8q04zd2jjycdb5196xdhgvqzk10abz";
};
meta = {
homepage = "https://github.com/keplerproject/luafilesystem";
hydraPlatforms = stdenv.lib.platforms.linux;
maintainers = with maintainers; [ flosse ];
};
};
</programlisting>
</para>
<para>
Though, more complicated package should be placed in a seperate file in
<link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/lua-modules"><filename>pkgs/development/lua-modules</filename></link>.
</para>
<para>
Lua packages accept additional parameter <varname>disabled</varname>, which defines
the condition of disabling package from luaPackages. For example, if package has
<varname>disabled</varname> assigned to <literal>lua.luaversion != "5.1"</literal>,
it will not be included in any luaPackages except lua51Packages, making it
only be built for lua 5.1.
</para>
</section>
<section xml:id="ssec-language-coq"><title>Coq</title>
<para>
Coq libraries should be installed in
<literal>$(out)/lib/coq/${coq.coq-version}/user-contrib/</literal>.
Such directories are automatically added to the
<literal>$COQPATH</literal> environment variable by the hook defined
in the Coq derivation.
</para>
<para>
Some libraries require OCaml and sometimes also Camlp5. The exact
versions that were used to build Coq are saved in the
<literal>coq.ocaml</literal> and <literal>coq.camlp5</literal>
attributes.
</para>
<para>
Here is a simple package example. It is a pure Coq library, thus it
only depends on Coq. Its <literal>makefile</literal> has been
generated using <literal>coq_makefile</literal> so we only have to
set the <literal>$COQLIB</literal> variable at install time.
</para>
<programlisting>
{stdenv, fetchurl, coq}:
stdenv.mkDerivation {
src = fetchurl {
url = http://coq.inria.fr/pylons/contribs/files/Karatsuba/v8.4/Karatsuba.tar.gz;
sha256 = "0ymfpv4v49k4fm63nq6gcl1hbnnxrvjjp7yzc4973n49b853c5b1";
};
name = "coq-karatsuba";
buildInputs = [ coq ];
installFlags = "COQLIB=$(out)/lib/coq/${coq.coq-version}/";
}
</programlisting>
</section>
<!-- <!--
<section><title>Haskell</title> <section><title>Haskell</title>

View File

@ -12,6 +12,7 @@
<xi:include href="introduction.xml" /> <xi:include href="introduction.xml" />
<xi:include href="quick-start.xml" /> <xi:include href="quick-start.xml" />
<xi:include href="stdenv.xml" /> <xi:include href="stdenv.xml" />
<xi:include href="packageconfig.xml" />
<xi:include href="meta.xml" /> <xi:include href="meta.xml" />
<xi:include href="language-support.xml" /> <xi:include href="language-support.xml" />
<xi:include href="package-notes.xml" /> <xi:include href="package-notes.xml" />

View File

@ -84,8 +84,7 @@ hello-2.3 A program that produces a familiar, friendly greeting
<section><title>Standard meta-attributes</title> <section><title>Standard meta-attributes</title>
<para>The following meta-attributes have a standard <para>It is expected that each meta-attribute is one of the following:</para>
interpretation:</para>
<variablelist> <variablelist>
@ -112,12 +111,30 @@ interpretation:</para>
package.</para></listitem> package.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>version</varname></term>
<listitem><para>Package version.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>branch</varname></term>
<listitem><para>Release branch. Used to specify that a package is not
going to receive updates that are not in this branch; for example, Linux
kernel 3.0 is supposed to be updated to 3.0.X, not 3.1.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>homepage</varname></term> <term><varname>homepage</varname></term>
<listitem><para>The packages homepage. Example: <listitem><para>The packages homepage. Example:
<literal>http://www.gnu.org/software/hello/manual/</literal></para></listitem> <literal>http://www.gnu.org/software/hello/manual/</literal></para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>downloadPage</varname></term>
<listitem><para>The page where a link to the current version can be found. Example:
<literal>http://ftp.gnu.org/gnu/hello/</literal></para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>license</varname></term> <term><varname>license</varname></term>
<listitem><para>The license for the package. One from the <listitem><para>The license for the package. One from the
@ -195,6 +212,16 @@ meta.hydraPlatforms = [];
they are fixed.</para></listitem> they are fixed.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>updateWalker</varname></term>
<listitem><para>If set to <literal>true</literal>, the package is
tested to be updated correctly by the <literal>update-walker.sh</literal>
script without additional settings. Such packages have
<varname>meta.version</varname> set and their homepage (or
the page specified by <varname>meta.downloadPage</varname>) contains
a direct link to the package tarball.</para></listitem>
</varlistentry>
</variablelist> </variablelist>
@ -256,9 +283,9 @@ to indicate the specific license:
</variablelist> </variablelist>
</para> </para>
</section> </section>
</chapter> </chapter>

View File

@ -184,10 +184,10 @@ if test "$noSysDirs" = "1"; then
if test "$noSysDirs" = "1"; then if test "$noSysDirs" = "1"; then
# Figure out what extra flags to pass to the gcc compilers # Figure out what extra flags to pass to the gcc compilers
# being generated to make sure that they use our glibc. # being generated to make sure that they use our glibc.
if test -e $NIX_GCC/nix-support/orig-glibc; then if test -e $NIX_CC/nix-support/orig-glibc; then
glibc=$(cat $NIX_GCC/nix-support/orig-glibc) glibc=$(cat $NIX_CC/nix-support/orig-glibc)
# Ugh. Copied from gcc-wrapper/builder.sh. We can't just # Ugh. Copied from gcc-wrapper/builder.sh. We can't just
# source in $NIX_GCC/nix-support/add-flags, since that # source in $NIX_CC/nix-support/add-flags, since that
# would cause *this* GCC to be linked against the # would cause *this* GCC to be linked against the
# *previous* GCC. Need some more modularity there. # *previous* GCC. Need some more modularity there.
extraCFlags="-B$glibc/lib -isystem $glibc/include" extraCFlags="-B$glibc/lib -isystem $glibc/include"

70
doc/packageconfig.xml Normal file
View File

@ -0,0 +1,70 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-packageconfig">
<title><filename>~/.nixpkgs/config.nix</filename>: global configuration</title>
<para>
Nix packages can be configured to allow or deny certain options.
</para>
<para>
To apply the configuration edit <filename>~/.nixpkgs/config.nix</filename>
and set it like
<programlisting>{
allowUnfree = true;
}</programlisting>
and will allow the Nix package manager to install unfree licensed packages.
The configuration as listed also applies to NixOS under <option>nixpkgs.config</option> set.
</para>
<itemizedlist>
<listitem>
<para>
Allow installing of packages that are distributed under unfree license by setting
<programlisting>allowUnfree = true;</programlisting>
or deny them by setting it to <literal>false</literal>.
</para>
<para>
Same can be achieved by setting the environment variable:
<programlisting>$ export NIXPKGS_ALLOW_UNFREE=1</programlisting>
</para>
</listitem>
<listitem>
<para>
Whenever unfree packages are not allowed, single packages can
still be allowed by a predicate function that accepts package
as an argument and should return a boolean:
<programlisting>allowUnfreePredicate = (pkg: ...);</programlisting>
Example to allow flash player only:
<programlisting>allowUnfreePredicate = (pkg: pkgs.lib.hasPrefix "flashplayer-" pkg.name);</programlisting>
</para>
</listitem>
<listitem>
<para>
Whenever unfree packages are not allowed, packages can still be
whitelisted by their license:
<programlisting>whitelistedLicenses = with stdenv.lib.licenses; [ amd wtfpl ];</programlisting>
</para>
</listitem>
<listitem>
<para>
In addition to whitelisting licenses which are denied by the
<literal>allowUnfree</literal> setting, you can also explicitely
deny installation of packages which have a certain license:
<programlisting>blacklistedLicenses = with stdenv.lib.licenses; [ agpl3 gpl3 ];</programlisting>
</para>
</listitem>
</itemizedlist>
<para>
A complete list of licenses can be found in the file
<filename>lib/licenses.nix</filename> of the nix package tree.
</para>
</chapter>

View File

@ -92,17 +92,6 @@ $ git add pkgs/development/libraries/libfoo/default.nix</screen>
hackery.</para> hackery.</para>
</listitem> </listitem>
<listitem>
<para>BitTorrent (wxPython-based): <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/networking/p2p/bittorrent/default.nix"><filename>pkgs/tools/networking/p2p/bittorrent/default.nix</filename></link>.
Uses an external <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/networking/p2p/bittorrent/builder.sh">build
script</link>, which can be useful if you have lots of code
that you dont want cluttering up the Nix expression. But
external builders are mostly obsolete.
</para>
</listitem>
<listitem> <listitem>
<para>Thunderbird: <link <para>Thunderbird: <link
xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/mailreaders/thunderbird/default.nix"><filename>pkgs/applications/networking/mailreaders/thunderbird/default.nix</filename></link>. xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/mailreaders/thunderbird/default.nix"><filename>pkgs/applications/networking/mailreaders/thunderbird/default.nix</filename></link>.

View File

@ -1,44 +0,0 @@
<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml"/>
<xsl:template match="function|command|literal|varname|filename|option|quote">`<xsl:apply-templates/>'</xsl:template>
<xsl:template match="token"><xsl:text> </xsl:text><xsl:apply-templates /><xsl:text>
</xsl:text></xsl:template>
<xsl:template match="screen|programlisting">
<screen><xsl:apply-templates select="str:split(., '&#xA;')" /></screen>
</xsl:template>
<xsl:template match="section[following::section]">
<section>
<xsl:apply-templates />
<screen><xsl:text>
</xsl:text></screen>
</section>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
<xsl:copy-of select="namespace::*" />
<xsl:for-each select="@*">
<xsl:attribute name="{name(.)}" namespace="{namespace-uri(.)}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="translate(., '‘’“”—', concat(&quot;`'&quot;, '&quot;&quot;-'))" />
</xsl:template>
</xsl:stylesheet>

View File

@ -150,8 +150,8 @@ genericBuild
<listitem><para>GNU <command>tar</command>.</para></listitem> <listitem><para>GNU <command>tar</command>.</para></listitem>
<listitem><para><command>gzip</command> and <listitem><para><command>gzip</command>, <command>bzip2</command>
<command>bzip2</command>.</para></listitem> and <command>xz</command>.</para></listitem>
<listitem><para>GNU Make. It has been patched to provide <listitem><para>GNU Make. It has been patched to provide
<quote>nested</quote> output that can be fed into the <quote>nested</quote> output that can be fed into the
@ -341,9 +341,11 @@ It supports the following files by default:
<term>Tar files</term> <term>Tar files</term>
<listitem><para>These can optionally be compressed using <listitem><para>These can optionally be compressed using
<command>gzip</command> (<filename>.tar.gz</filename>, <command>gzip</command> (<filename>.tar.gz</filename>,
<filename>.tgz</filename> or <filename>.tar.Z</filename>) or <filename>.tgz</filename> or <filename>.tar.Z</filename>),
<command>bzip2</command> (<filename>.tar.bz2</filename> or <command>bzip2</command> (<filename>.tar.bz2</filename> or
<filename>.tbz2</filename>).</para></listitem> <filename>.tbz2</filename>) or <command>xz</command>
(<filename>.tar.xz</filename> or
<filename>.tar.lzma</filename>).</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -445,9 +447,10 @@ Additional file types can be supported by setting the
<listitem><para>The list of patches. They must be in the format <listitem><para>The list of patches. They must be in the format
accepted by the <command>patch</command> command, and may accepted by the <command>patch</command> command, and may
optionally be compressed using <command>gzip</command> optionally be compressed using <command>gzip</command>
(<filename>.gz</filename>) or <command>bzip2</command> (<filename>.gz</filename>), <command>bzip2</command>
(<filename>.bz2</filename>).</para></listitem> (<filename>.bz2</filename>) or <command>xz</command>
</varlistentry> (<filename>.xz</filename>).</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>patchFlags</varname></term> <term><varname>patchFlags</varname></term>
@ -715,7 +718,7 @@ the Nix store under <envar>out</envar>. The default
install</command>.</para> install</command>.</para>
<variablelist> <variablelist>
<title>Variables controlling the check phase</title> <title>Variables controlling the install phase</title>
<varlistentry> <varlistentry>
<term><varname>makeFlags</varname> / <term><varname>makeFlags</varname> /
@ -794,7 +797,7 @@ following:
</para> </para>
<variablelist> <variablelist>
<title>Variables controlling the check phase</title> <title>Variables controlling the fixup phase</title>
<varlistentry> <varlistentry>
<term><varname>dontStrip</varname></term> <term><varname>dontStrip</varname></term>
@ -1117,12 +1120,9 @@ echo @foo@
<varlistentry> <varlistentry>
<term>Python</term> <term>Python</term>
<listitem><para>Adds the <listitem><para>Adds the
<filename>lib/python2.5/site-packages</filename> subdirectory of <filename>lib/${python.libPrefix}/site-packages</filename> subdirectory of
each build input to the <envar>PYTHONPATH</envar> environment each build input to the <envar>PYTHONPATH</envar> environment
variable.</para> variable.</para></listitem>
<note><para>This should be generalised: the Python version
shouldnt be hard-coded.</para></note></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -1,7 +1,7 @@
# Operations on attribute sets. # Operations on attribute sets.
with { with {
inherit (builtins) head tail; inherit (builtins) head tail length;
inherit (import ./trivial.nix) or; inherit (import ./trivial.nix) or;
inherit (import ./default.nix) fold; inherit (import ./default.nix) fold;
inherit (import ./strings.nix) concatStringsSep; inherit (import ./strings.nix) concatStringsSep;
@ -20,8 +20,8 @@ rec {
let attr = head attrPath; let attr = head attrPath;
in in
if attrPath == [] then e if attrPath == [] then e
else if hasAttr attr e else if e ? ${attr}
then attrByPath (tail attrPath) default (getAttr attr e) then attrByPath (tail attrPath) default e.${attr}
else default; else default;
@ -44,8 +44,7 @@ rec {
attrVals ["a" "b" "c"] as attrVals ["a" "b" "c"] as
=> [as.a as.b as.c] => [as.a as.b as.c]
*/ */
attrVals = nameList: set: attrVals = nameList: set: map (x: set.${x}) nameList;
map (x: getAttr x set) nameList;
/* Return the values of all attributes in the given set, sorted by /* Return the values of all attributes in the given set, sorted by
@ -55,7 +54,7 @@ rec {
attrValues {c = 3; a = 1; b = 2;} attrValues {c = 3; a = 1; b = 2;}
=> [1 2 3] => [1 2 3]
*/ */
attrValues = attrs: attrVals (attrNames attrs) attrs; attrValues = builtins.attrValues or (attrs: attrVals (attrNames attrs) attrs);
/* Collect each attribute named `attr' from a list of attribute /* Collect each attribute named `attr' from a list of attribute
@ -65,7 +64,8 @@ rec {
catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}] catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
=> [1 2] => [1 2]
*/ */
catAttrs = attr: l: concatLists (map (s: if hasAttr attr s then [(getAttr attr s)] else []) l); catAttrs = builtins.catAttrs or
(attr: l: concatLists (map (s: if s ? ${attr} then [s.${attr}] else []) l));
/* Filter an attribute set by removing all attributes for which the /* Filter an attribute set by removing all attributes for which the
@ -76,7 +76,7 @@ rec {
=> { foo = 1; } => { foo = 1; }
*/ */
filterAttrs = pred: set: filterAttrs = pred: set:
listToAttrs (fold (n: ys: let v = getAttr n set; in if pred n v then [(nameValuePair n v)] ++ ys else ys) [] (attrNames set)); listToAttrs (fold (n: ys: let v = set.${n}; in if pred n v then [(nameValuePair n v)] ++ ys else ys) [] (attrNames set));
/* foldAttrs: apply fold functions to values grouped by key. Eg accumulate values as list: /* foldAttrs: apply fold functions to values grouped by key. Eg accumulate values as list:
@ -86,7 +86,7 @@ rec {
foldAttrs = op: nul: list_of_attrs: foldAttrs = op: nul: list_of_attrs:
fold (n: a: fold (n: a:
fold (name: o: fold (name: o:
o // (listToAttrs [{inherit name; value = op (getAttr name n) (maybeAttr name nul a); }]) o // (listToAttrs [{inherit name; value = op n.${name} (maybeAttr name nul a); }])
) a (attrNames n) ) a (attrNames n)
) {} list_of_attrs; ) {} list_of_attrs;
@ -132,7 +132,7 @@ rec {
=> { x = "x-foo"; y = "y-bar"; } => { x = "x-foo"; y = "y-bar"; }
*/ */
mapAttrs = f: set: mapAttrs = f: set:
listToAttrs (map (attr: { name = attr; value = f attr (getAttr attr set); }) (attrNames set)); listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set));
/* Like `mapAttrs', but allows the name of each attribute to be /* Like `mapAttrs', but allows the name of each attribute to be
@ -145,7 +145,7 @@ rec {
=> { foo_x = "bar-a"; foo_y = "bar-b"; } => { foo_x = "bar-a"; foo_y = "bar-b"; }
*/ */
mapAttrs' = f: set: mapAttrs' = f: set:
listToAttrs (map (attr: f attr (getAttr attr set)) (attrNames set)); listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
/* Call a function for each attribute in the given set and return /* Call a function for each attribute in the given set and return
@ -157,7 +157,7 @@ rec {
=> [ "xa" "yb" ] => [ "xa" "yb" ]
*/ */
mapAttrsToList = f: attrs: mapAttrsToList = f: attrs:
map (name: f name (getAttr name attrs)) (attrNames attrs); map (name: f name attrs.${name}) (attrNames attrs);
/* Like `mapAttrs', except that it recursively applies itself to /* Like `mapAttrs', except that it recursively applies itself to
@ -322,7 +322,7 @@ rec {
# override only the attributes that are already present in the old set # override only the attributes that are already present in the old set
# useful for deep-overriding # useful for deep-overriding
overrideExisting = old: new: overrideExisting = old: new:
old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] (getAttr attr old) new)) (attrNames old)); old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] old.${attr} new)) (attrNames old));
deepSeqAttrs = x: y: deepSeqList (attrValues x) y; deepSeqAttrs = x: y: deepSeqList (attrValues x) y;
} }

View File

@ -1,6 +1,6 @@
let lib = import ./default.nix; let
inherit (builtins) getAttr attrNames isFunction; lib = import ./default.nix;
inherit (builtins) attrNames isFunction;
in in
rec { rec {
@ -29,8 +29,8 @@ rec {
For another application, see build-support/vm, where this For another application, see build-support/vm, where this
function is used to build arbitrary derivations inside a QEMU function is used to build arbitrary derivations inside a QEMU
virtual machine. */ virtual machine.
*/
overrideDerivation = drv: f: overrideDerivation = drv: f:
let let
newDrv = derivation (drv.drvAttrs // (f drv)); newDrv = derivation (drv.drvAttrs // (f drv));
@ -56,13 +56,21 @@ rec {
makeOverridable = f: origArgs: makeOverridable = f: origArgs:
let let
ff = f origArgs; ff = f origArgs;
overrideWith = newArgs: origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs);
in in
if builtins.isAttrs ff then (ff // if builtins.isAttrs ff then (ff //
{ override = newArgs: { override = newArgs: makeOverridable f (overrideWith newArgs);
makeOverridable f (origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs));
deepOverride = newArgs: deepOverride = newArgs:
makeOverridable f (lib.overrideExisting (lib.mapAttrs (deepOverrider newArgs) origArgs) newArgs); makeOverridable f (lib.overrideExisting (lib.mapAttrs (deepOverrider newArgs) origArgs) newArgs);
overrideDerivation = fdrv:
makeOverridable (args: overrideDerivation (f args) fdrv) origArgs;
}) })
else if builtins.isFunction ff then
{ override = newArgs: makeOverridable f (overrideWith newArgs);
__functor = self: ff;
deepOverride = throw "deepOverride not yet supported for functors";
overrideDerivation = throw "overrideDerivation not yet supported for functors";
}
else ff; else ff;
deepOverrider = newArgs: name: x: if builtins.isAttrs x then ( deepOverrider = newArgs: name: x: if builtins.isAttrs x then (
@ -93,8 +101,11 @@ rec {
}; };
*/ */
callPackageWith = autoArgs: fn: args: callPackageWith = autoArgs: fn: args:
let f = if builtins.isFunction fn then fn else import fn; in let
makeOverridable f ((builtins.intersectAttrs (builtins.functionArgs f) autoArgs) // args); f = if builtins.isFunction fn then fn else import fn;
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
in makeOverridable f (auto // args);
/* Add attributes to each output of a derivation without changing the derivation itself */ /* Add attributes to each output of a derivation without changing the derivation itself */
addPassthru = drv: passthru: addPassthru = drv: passthru:
@ -107,10 +118,44 @@ rec {
outputToAttrListElement = outputName: outputToAttrListElement = outputName:
{ name = outputName; { name = outputName;
value = commonAttrs // { value = commonAttrs // {
inherit (builtins.getAttr outputName drv) outPath drvPath type outputName; inherit (drv.${outputName}) outPath drvPath type outputName;
}; };
}; };
outputsList = map outputToAttrListElement outputs; outputsList = map outputToAttrListElement outputs;
in builtins.getAttr drv.outputName commonAttrs; in commonAttrs.${drv.outputName};
/* Strip a derivation of all non-essential attributes, returning
only those needed by hydra-eval-jobs. Also strictly evaluate the
result to ensure that there are no thunks kept alive to prevent
garbage collection. */
hydraJob = drv:
let
outputs = drv.outputs or ["out"];
commonAttrs =
{ inherit (drv) name system meta; inherit outputs; }
// lib.optionalAttrs (drv._hydraAggregate or false) {
_hydraAggregate = true;
constituents = map hydraJob (lib.flatten drv.constituents);
}
// (lib.listToAttrs outputsList);
makeOutput = outputName:
let output = drv.${outputName}; in
{ name = outputName;
value = commonAttrs // {
outPath = output.outPath;
drvPath = output.drvPath;
type = "derivation";
inherit outputName;
};
};
outputsList = map makeOutput outputs;
drv' = (lib.head outputsList).value;
in lib.deepSeq drv' drv';
} }

View File

@ -9,23 +9,16 @@ in
rec { rec {
inherit (builtins) addErrorContext;
# Wrapper aroung the primop `addErrorContext', which shouldn't used addErrorContextToAttrs = lib.mapAttrs (a: v: lib.addErrorContext "while evaluating ${a}" v);
# directly. It evaluates and returns `val', but if an evaluation
# error occurs, the text in `msg' is added to the error context
# (stack trace) printed by Nix.
addErrorContext =
if builtins ? addErrorContext
then builtins.addErrorContext
else msg: val: val;
addErrorContextToAttrs = lib.mapAttrs (a : v : lib.addErrorContext "while evaluating ${a}" v); traceIf = p: msg: x: if p then trace msg x else x;
traceVal = x: trace x x;
traceXMLVal = x: trace (builtins.toXML x) x;
traceXMLValMarked = str: x: trace (str + builtins.toXML x) x;
traceVal = if builtins ? trace then x: (builtins.trace x x) else x: x;
traceXMLVal = if builtins ? trace then x: (builtins.trace (builtins.toXML x) x) else x: x;
traceXMLValMarked = str: if builtins ? trace then x: (builtins.trace ( str + builtins.toXML x) x) else x: x;
# this can help debug your code as well - designed to not produce thousands of lines # this can help debug your code as well - designed to not produce thousands of lines
traceShowVal = x : trace (showVal x) x; traceShowVal = x : trace (showVal x) x;
traceShowValMarked = str: x: trace (str + showVal x) x; traceShowValMarked = str: x: trace (str + showVal x) x;
@ -44,12 +37,13 @@ rec {
else if isString x then "x is a string `${substring 0 50 x}...'" else if isString x then "x is a string `${substring 0 50 x}...'"
else "x is probably a path `${substring 0 50 (toString x)}...'"; else "x is probably a path `${substring 0 50 (toString x)}...'";
# trace the arguments passed to function and its result # trace the arguments passed to function and its result
# maybe rewrite these functions in a traceCallXml like style. Then one function is enough # maybe rewrite these functions in a traceCallXml like style. Then one function is enough
traceCall = n : f : a : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a)); traceCall = n : f : a : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
traceCall2 = n : f : a : b : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b)); traceCall2 = n : f : a : b : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
traceCall3 = n : f : a : b : c : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c)); traceCall3 = n : f : a : b : c : let t = n2 : x : traceShowValMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
# FIXME: rename this?
traceValIfNot = c: x: traceValIfNot = c: x:
if c x then true else trace (showVal x) false; if c x then true else trace (showVal x) false;
@ -70,7 +64,7 @@ rec {
then [ { inherit name; expected = test.expected; result = test.expr; } ] then [ { inherit name; expected = test.expected; result = test.expr; } ]
else [] ) tests)); else [] ) tests));
# create a test assuming that list elements are true # create a test assuming that list elements are true
# usage: { testX = allTrue [ true ]; } # usage: { testX = allTrue [ true ]; }
testAllTrue = expr : { inherit expr; expected = map (x: true) expr; }; testAllTrue = expr : { inherit expr; expected = map (x: true) expr; };
@ -109,11 +103,11 @@ rec {
let nr = a; let nr = a;
in (str: expr: in (str: expr:
if isFunction expr then if isFunction expr then
(arg: (arg:
traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (strict arg)}" (expr arg) traceCallXml (builtins.add 1 nr) "${str}\n arg ${builtins.toString nr} is \n ${builtins.toXML (strict arg)}" (expr arg)
) )
else else
let r = strict expr; let r = strict expr;
in builtins.trace "${str}\n result:\n${builtins.toXML r}" r in trace "${str}\n result:\n${builtins.toXML r}" r
); );
} }

View File

@ -1,283 +1,441 @@
let let
lib = import ./default.nix;
spdx = lic: lic // { spdx = lic: lic // {
url = "http://spdx.org/licenses/${lic.shortName}"; url = "http://spdx.org/licenses/${lic.spdxId}";
}; };
in in
rec { lib.mapAttrs (n: v: v // { shortName = n; }) rec {
/* License identifiers from spdx.org where possible. /* License identifiers from spdx.org where possible.
* If you cannot find your license here, then look for a similar license or * If you cannot find your license here, then look for a similar license or
* add it to this list. The URL mentioned above is a good source for inspiration. * add it to this list. The URL mentioned above is a good source for inspiration.
*/ */
afl21 = spdx {
spdxId = "AFL-2.1";
fullName = "Academic Free License";
};
agpl3 = spdx { agpl3 = spdx {
shortName = "AGPL-3.0"; spdxId = "AGPL-3.0";
fullName = "GNU Affero General Public License v3.0"; fullName = "GNU Affero General Public License v3.0";
}; };
agpl3Plus = { agpl3Plus = {
shortName = "AGPL-3.0+";
fullName = "GNU Affero General Public License v3.0 or later"; fullName = "GNU Affero General Public License v3.0 or later";
inherit (agpl3) url; inherit (agpl3) url;
}; };
amazonsl = {
fullName = "Amazon Software License";
url = http://aws.amazon.com/asl/;
free = false;
};
amd = { amd = {
shortName = "amd";
fullName = "AMD License Agreement"; fullName = "AMD License Agreement";
url = http://developer.amd.com/amd-license-agreement/; url = http://developer.amd.com/amd-license-agreement/;
};# };
apsl20 = spdx { apsl20 = spdx {
shortName = "APSL-2.0"; spdxId = "APSL-2.0";
fullName = "Apple Public Source License 2.0"; fullName = "Apple Public Source License 2.0";
}; };
artistic1 = spdx {
spdxId = "Artistic-1.0";
fullName = "Artistic License 1.0";
};
artistic2 = spdx { artistic2 = spdx {
shortName = "Artistic-2.0"; spdxId = "Artistic-2.0";
fullName = "Artistic License 2.0"; fullName = "Artistic License 2.0";
}; };
asl20 = spdx { asl20 = spdx {
shortName = "Apache-2.0"; spdxId = "Apache-2.0";
fullName = "Apache License 2.0"; fullName = "Apache License 2.0";
}; };
boost = spdx { boost = spdx {
shortName = "BSL-1.0"; spdxId = "BSL-1.0";
fullName = "Boost Software License 1.0"; fullName = "Boost Software License 1.0";
}; };
bsd2 = spdx { bsd2 = spdx {
shortName = "BSD-2-Clause"; spdxId = "BSD-2-Clause";
fullName = ''BSD 2-clause "Simplified" License''; fullName = ''BSD 2-clause "Simplified" License'';
}; };
bsd3 = spdx { bsd3 = spdx {
shortName = "BSD-3-Clause"; spdxId = "BSD-3-Clause";
fullName = ''BSD 3-clause "New" or "Revised" License''; fullName = ''BSD 3-clause "New" or "Revised" License'';
}; };
bsdOriginal = spdx { bsdOriginal = spdx {
shortName = "BSD-4-Clause"; spdxId = "BSD-4-Clause";
fullName = ''BSD 4-clause "Original" or "Old" License''; fullName = ''BSD 4-clause "Original" or "Old" License'';
}; };
cc0 = spdx { cc0 = spdx {
shortName = "CC0-1.0"; spdxId = "CC0-1.0";
fullName = ''Creative Commons Zero v1.0 Universal''; fullName = "Creative Commons Zero v1.0 Universal";
}; };
cc-by-30 = spdx { cc-by-30 = spdx {
shortName = "CC-BY-3.0"; spdxId = "CC-BY-3.0";
fullName = "Creative Commons Attribution 3.0"; fullName = "Creative Commons Attribution 3.0";
}; };
cc-by-sa-30 = spdx {
spdxId = "CC-BY-SA-3.0";
fullName = "Creative Commons Attribution Share Alike 3.0";
};
cc-by-40 = spdx {
spdxId = "CC-BY-4.0";
fullName = "Creative Commons Attribution 4.0";
};
cc-by-sa-40 = spdx {
spdxId = "CC-BY-SA-4.0";
fullName = "Creative Commons Attribution Share Alike 4.0";
};
cddl = spdx { cddl = spdx {
shortName = "CDDL-1.0"; spdxId = "CDDL-1.0";
fullName = "Common Development and Distribution License 1.0"; fullName = "Common Development and Distribution License 1.0";
}; };
cecill20 = spdx {
spdxId = "CECILL-2.0";
fullName = "CeCILL Free Software License Agreement v2.0";
};
cecill-b = spdx {
spdxId = "CECILL-B";
fullName = "CeCILL-B Free Software License Agreement";
};
cecill-c = spdx { cecill-c = spdx {
shortName = "CECILL-C"; spdxId = "CECILL-C";
fullName = "CeCILL-C Free Software License Agreement"; fullName = "CeCILL-C Free Software License Agreement";
}; };
cpl10 = spdx { cpl10 = spdx {
shortName = "CPL-1.0"; spdxId = "CPL-1.0";
fullName = "Common Public License 1.0"; fullName = "Common Public License 1.0";
}; };
efl10 = spdx {
spdxId = "EFL-1.0";
fullName = "Eiffel Forum License v1.0";
};
efl20 = spdx {
spdxId = "EFL-2.0";
fullName = "Eiffel Forum License v2.0";
};
epl10 = spdx { epl10 = spdx {
shortName = "EPL-1.0"; spdxId = "EPL-1.0";
fullName = "Eclipse Public License 1.0"; fullName = "Eclipse Public License 1.0";
}; };
free = "free"; fdl12 = spdx {
spdxId = "GFDL-1.2";
fullName = "GNU Free Documentation License v1.2";
};
free = {
fullName = "Unspecified free software license";
};
gpl1 = spdx {
spdxId = "GPL-1.0";
fullName = "GNU General Public License v1.0 only";
};
gpl1Plus = spdx {
spdxId = "GPL-1.0+";
fullName = "GNU General Public License v1.0 or later";
};
gpl2 = spdx { gpl2 = spdx {
shortName = "GPL-2.0"; spdxId = "GPL-2.0";
fullName = "GNU General Public License v2.0 only"; fullName = "GNU General Public License v2.0 only";
}; };
gpl2ClasspathPlus = {
fullName = "GNU General Public License v2.0 or later (with Classpath exception)";
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
};
gpl2Oss = { gpl2Oss = {
shortName = "GPL-2.0-with-OSS";
fullName = "GNU General Public License version 2 only (with OSI approved licenses linking exception)"; fullName = "GNU General Public License version 2 only (with OSI approved licenses linking exception)";
url = http://www.mysql.com/about/legal/licensing/foss-exception; url = http://www.mysql.com/about/legal/licensing/foss-exception;
}; };
gpl2Plus = spdx { gpl2Plus = spdx {
shortName = "GPL-2.0+"; spdxId = "GPL-2.0+";
fullName = "GNU General Public License v2.0 or later"; fullName = "GNU General Public License v2.0 or later";
}; };
gpl3 = spdx { gpl3 = spdx {
shortName = "GPL-3.0"; spdxId = "GPL-3.0";
fullName = "GNU General Public License v3.0 only"; fullName = "GNU General Public License v3.0 only";
}; };
gpl3Plus = spdx { gpl3Plus = spdx {
shortName = "GPL-3.0+"; spdxId = "GPL-3.0+";
fullName = "GNU General Public License v3.0 or later"; fullName = "GNU General Public License v3.0 or later";
}; };
gpl3ClasspathPlus = { gpl3ClasspathPlus = {
shortName = "GPL-3.0+-with-classpath-exception";
fullName = "GNU General Public License v3.0 or later (with Classpath exception)"; fullName = "GNU General Public License v3.0 or later (with Classpath exception)";
url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception; url = https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception;
}; };
# Intel's license, seems free
iasl = {
fullName = "iASL";
url = http://www.calculate-linux.org/packages/licenses/iASL;
};
ijg = spdx {
spdxId = "IJG";
fullName = "Independent JPEG Group License";
};
inria = { inria = {
shortName = "INRIA-NCLA";
fullName = "INRIA Non-Commercial License Agreement"; fullName = "INRIA Non-Commercial License Agreement";
url = "http://compcert.inria.fr/doc/LICENSE"; url = "http://compcert.inria.fr/doc/LICENSE";
}; };
ipa = spdx { ipa = spdx {
shortName = "IPA"; spdxId = "IPA";
fullName = "IPA Font License"; fullName = "IPA Font License";
}; };
ipl10 = spdx { ipl10 = spdx {
shortName = "IPL-1.0"; spdxId = "IPL-1.0";
fullName = "IBM Public License v1.0"; fullName = "IBM Public License v1.0";
}; };
isc = spdx { isc = spdx {
shortName = "ISC"; spdxId = "ISC";
fullName = "ISC License"; fullName = "ISC License";
}; };
lgpl2 = spdx { lgpl2 = spdx {
shortName = "LGPL-2.0"; spdxId = "LGPL-2.0";
fullName = "GNU Library General Public License v2 only"; fullName = "GNU Library General Public License v2 only";
}; };
lgpl2Plus = spdx { lgpl2Plus = spdx {
shortName = "LGPL-2.0+"; spdxId = "LGPL-2.0+";
fullName = "GNU Library General Public License v2 or later"; fullName = "GNU Library General Public License v2 or later";
}; };
lgpl21 = spdx { lgpl21 = spdx {
shortName = "LGPL-2.1"; spdxId = "LGPL-2.1";
fullName = "GNU Library General Public License v2.1 only"; fullName = "GNU Library General Public License v2.1 only";
}; };
lgpl21Plus = spdx { lgpl21Plus = spdx {
shortName = "LGPL-2.1+"; spdxId = "LGPL-2.1+";
fullName = "GNU Library General Public License v2.1 or later"; fullName = "GNU Library General Public License v2.1 or later";
}; };
lgpl3 = spdx { lgpl3 = spdx {
shortName = "LGPL-3.0"; spdxId = "LGPL-3.0";
fullName = "GNU Lesser General Public License v3.0 only"; fullName = "GNU Lesser General Public License v3.0 only";
}; };
lgpl3Plus = spdx { lgpl3Plus = spdx {
shortName = "LGPL-3.0+"; spdxId = "LGPL-3.0+";
fullName = "GNU Lesser General Public License v3.0 or later"; fullName = "GNU Lesser General Public License v3.0 or later";
}; };
libtiff = { libpng = spdx {
shortName = "libtiff"; spdxId = "Libpng";
fullName = "libtiff license"; fullName = "libpng License";
url = https://fedoraproject.org/wiki/Licensing/libtiff; };
libtiff = spdx {
spdxId = "libtiff";
fullName = "libtiff License";
}; };
llgpl21 = { llgpl21 = {
shortName = "LLGPL-2.1";
fullName = "Lisp LGPL; GNU Lesser General Public License version 2.1 with Franz Inc. preamble for clarification of LGPL terms in context of Lisp"; fullName = "Lisp LGPL; GNU Lesser General Public License version 2.1 with Franz Inc. preamble for clarification of LGPL terms in context of Lisp";
url = http://opensource.franz.com/preamble.html; url = http://opensource.franz.com/preamble.html;
}; };
lppl12 = spdx {
spdxId = "LPPL-1.2";
fullName = "LaTeX Project Public License v1.2";
};
lppl13c = spdx {
spdxId = "LPPL-1.3c";
fullName = "LaTeX Project Public License v1.3c";
};
lpl-102 = spdx { lpl-102 = spdx {
shortName = "LPL-1.02"; spdxId = "LPL-1.02";
fullName = "Lucent Public License v1.02"; fullName = "Lucent Public License v1.02";
}; };
# spdx.org does not (yet) differentiate between the X11 and Expat versions
# for details see http://en.wikipedia.org/wiki/MIT_License#Various_versions
mit = spdx { mit = spdx {
shortName = "MIT"; spdxId = "MIT";
fullName = "MIT License"; fullName = "MIT License";
}; };
mpl10 = spdx {
spdxId = "MPL-1.0";
fullName = "Mozilla Public License 1.0";
};
mpl11 = spdx { mpl11 = spdx {
shortName = "MPL-1.1"; spdxId = "MPL-1.1";
fullName = "Mozilla Public License 1.1"; fullName = "Mozilla Public License 1.1";
}; };
mpl20 = spdx { mpl20 = spdx {
shortName = "MPL-2.0"; spdxId = "MPL-2.0";
fullName = "Mozilla Public License 2.0"; fullName = "Mozilla Public License 2.0";
}; };
msrla = { msrla = {
shortName = "MSR-LA";
fullName = "Microsoft Research License Agreement"; fullName = "Microsoft Research License Agreement";
url = "http://research.microsoft.com/en-us/projects/pex/msr-la.txt"; url = "http://research.microsoft.com/en-us/projects/pex/msr-la.txt";
}; };
ncsa = spdx { ncsa = spdx {
shortName = "NCSA"; spdxId = "NCSA";
fullName = "University of Illinois/NCSA Open Source License"; fullName = "University of Illinois/NCSA Open Source License";
}; };
ofl = spdx { ofl = spdx {
shortName = "OFL-1.1"; spdxId = "OFL-1.1";
fullName = "SIL Open Font License 1.1"; fullName = "SIL Open Font License 1.1";
}; };
openssl = spdx { openssl = spdx {
shortName = "OpenSSL"; spdxId = "OpenSSL";
fullName = "OpenSSL License"; fullName = "OpenSSL License";
}; };
php301 = spdx {
spdxId = "PHP-3.01";
fullName = "PHP License v3.01";
};
postgresql = spdx {
spdxId = "PostgreSQL";
fullName = "PostgreSQL License";
};
psfl = spdx { psfl = spdx {
shortName = "Python-2.0"; spdxId = "Python-2.0";
fullName = "Python Software Foundation License version 2"; fullName = "Python Software Foundation License version 2";
#url = http://docs.python.org/license.html; #url = http://docs.python.org/license.html;
}; };
publicDomain = { publicDomain = {
shortName = "Public Domain"; fullName = "Public Domain";
fullname = "Public Domain"; };
qpl = spdx {
spdxId = "QPL-1.0";
fullName = "Q Public License 1.0";
};
qwt = {
fullName = "Qwt License, Version 1.0";
url = http://qwt.sourceforge.net/qwtlicense.html;
};
ruby = spdx {
spdxId = "Ruby";
fullName = "Ruby License";
};
sgi-b-20 = spdx {
spdxId = "SGI-B-2.0";
fullName = "SGI Free Software License B v2.0";
}; };
sleepycat = spdx { sleepycat = spdx {
shortName = "Sleepycat"; spdxId = "Sleepycat";
fullName = "Sleepycat License"; fullName = "Sleepycat License";
}; };
tcltk = { tcltk = spdx {
shortName = "Tcl/Tk"; spdxId = "TCL";
fullName = "Tcl/Tk license"; fullName = "TCL/TK License";
url = http://www.tcl.tk/software/tcltk/license.html;
}; };
unfree = "unfree"; unfree = {
fullName = "Unfree";
free = false;
};
unfreeRedistributable = "unfree-redistributable"; unfreeRedistributable = {
fullName = "Unfree redistributable";
free = false;
};
unfreeRedistributableFirmware = "unfree-redistributable-firmware"; unfreeRedistributableFirmware = {
fullName = "Unfree redistributable firmware";
# Note: we currently consider these "free" for inclusion in the
# channel and NixOS images.
};
unlicense = spdx {
spdxId = "Unlicense";
fullName = "The Unlicense";
};
vsl10 = spdx {
spdxId = "VSL-1.0";
fullName = "Vovida Software License v1.0";
};
w3c = spdx {
spdxId = "W3C";
fullName = "W3C Software Notice and License";
};
wadalab = { wadalab = {
shortName = "wadalab";
fullName = "Wadalab Font License"; fullName = "Wadalab Font License";
url = https://fedoraproject.org/wiki/Licensing:Wadalab?rd=Licensing/Wadalab; url = https://fedoraproject.org/wiki/Licensing:Wadalab?rd=Licensing/Wadalab;
}; };
wtfpl = spdx {
spdxId = "WTFPL";
fullName = "Do What The F*ck You Want To Public License";
};
zlib = spdx { zlib = spdx {
shortName = "Zlib"; spdxId = "Zlib";
fullName = "zlib License"; fullName = "zlib License";
}; };
zpt20 = spdx { # FIXME: why zpt* instead of zpl* zpt20 = spdx { # FIXME: why zpt* instead of zpl*
shortName = "ZPL-2.0"; spdxId = "ZPL-2.0";
fullName = "Zope Public License 2.0"; fullName = "Zope Public License 2.0";
}; };
zpt21 = spdx { zpt21 = spdx {
shortName = "ZPL-2.1"; spdxId = "ZPL-2.1";
fullName = "Zope Public License 2.1"; fullName = "Zope Public License 2.1";
}; };
} }

View File

@ -2,13 +2,7 @@
with import ./trivial.nix; with import ./trivial.nix;
let rec {
inc = builtins.add 1;
dec = n: builtins.sub n 1;
in rec {
inherit (builtins) head tail length isList elemAt concatLists filter elem; inherit (builtins) head tail length isList elemAt concatLists filter elem;
@ -29,7 +23,7 @@ in rec {
fold' = n: fold' = n:
if n == len if n == len
then nul then nul
else op (elemAt list n) (fold' (inc n)); else op (elemAt list n) (fold' (n + 1));
in fold' 0; in fold' 0;
# Left fold: `fold op nul [x_1 x_2 ... x_n] == op (... (op (op nul # Left fold: `fold op nul [x_1 x_2 ... x_n] == op (... (op (op nul
@ -38,12 +32,10 @@ in rec {
let let
len = length list; len = length list;
foldl' = n: foldl' = n:
if n == minus1 if n == -1
then nul then nul
else op (foldl' (dec n)) (elemAt list n); else op (foldl' (n - 1)) (elemAt list n);
in foldl' (dec (length list)); in foldl' (length list - 1);
minus1 = dec 0;
# map with index: `imap (i: v: "${v}-${toString i}") ["a" "b"] == # map with index: `imap (i: v: "${v}-${toString i}") ["a" "b"] ==
@ -54,7 +46,7 @@ in rec {
imap' = n: imap' = n:
if n == len if n == len
then [] then []
else [ (f (inc n) (elemAt list n)) ] ++ imap' (inc n); else [ (f (n + 1) (elemAt list n)) ] ++ imap' (n + 1);
in imap' 0; in imap' 0;
@ -104,7 +96,7 @@ in rec {
# Count how many times function `pred' returns true for the elements # Count how many times function `pred' returns true for the elements
# of `list'. # of `list'.
count = pred: fold (x: c: if pred x then inc c else c) 0; count = pred: fold (x: c: if pred x then c + 1 else c) 0;
# Return a singleton list or an empty list, depending on a boolean # Return a singleton list or an empty list, depending on a boolean
@ -125,9 +117,9 @@ in rec {
# Return a list of integers from `first' up to and including `last'. # Return a list of integers from `first' up to and including `last'.
range = first: last: range = first: last:
if lessThan last first if last < first
then [] then []
else [first] ++ range (add first 1) last; else [first] ++ range (first + 1) last;
# Partition the elements of a list in two lists, `right' and # Partition the elements of a list in two lists, `right' and
@ -144,11 +136,11 @@ in rec {
let let
len1 = length fst; len1 = length fst;
len2 = length snd; len2 = length snd;
len = if lessThan len1 len2 then len1 else len2; len = if len1 < len2 then len1 else len2;
zipListsWith' = n: zipListsWith' = n:
if n != len then if n != len then
[ (f (elemAt fst n) (elemAt snd n)) ] [ (f (elemAt fst n) (elemAt snd n)) ]
++ zipListsWith' (inc n) ++ zipListsWith' (n + 1)
else []; else [];
in zipListsWith' 0; in zipListsWith' 0;
@ -167,7 +159,7 @@ in rec {
let let
len = length list; len = length list;
first = head list; first = head list;
pivot' = n: acc@{ left, right }: let el = elemAt list n; next = pivot' (inc n); in pivot' = n: acc@{ left, right }: let el = elemAt list n; next = pivot' (n + 1); in
if n == len if n == len
then acc then acc
else if strictLess first el else if strictLess first el
@ -176,7 +168,7 @@ in rec {
next { left = [ el ] ++ left; inherit right; }; next { left = [ el ] ++ left; inherit right; };
pivot = pivot' 1 { left = []; right = []; }; pivot = pivot' 1 { left = []; right = []; };
in in
if lessThan len 2 then list if len < 2 then list
else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right); else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right);
@ -188,7 +180,7 @@ in rec {
if n == len || n == count if n == len || n == count
then [] then []
else else
[ (elemAt list n) ] ++ take' (inc n); [ (elemAt list n) ] ++ take' (n + 1);
in take' 0; in take' 0;
@ -197,16 +189,20 @@ in rec {
let let
len = length list; len = length list;
drop' = n: drop' = n:
if n == minus1 || lessThan n count if n == -1 || n < count
then [] then []
else else
drop' (dec n) ++ [ (elemAt list n) ]; drop' (n - 1) ++ [ (elemAt list n) ];
in drop' (dec len); in drop' (len - 1);
# Return the last element of a list. # Return the last element of a list.
last = list: last = list:
assert list != []; elemAt list (dec (length list)); assert list != []; elemAt list (length list - 1);
# Return all elements but the last
init = list: assert list != []; take (length list - 1) list;
# Zip two lists together. # Zip two lists together.
@ -214,11 +210,11 @@ in rec {
let let
len1 = length xs; len1 = length xs;
len2 = length ys; len2 = length ys;
len = if lessThan len1 len2 then len1 else len2; len = if len1 < len2 then len1 else len2;
zipTwoLists' = n: zipTwoLists' = n:
if n != len then if n != len then
[ { first = elemAt xs n; second = elemAt ys n; } ] [ { first = elemAt xs n; second = elemAt ys n; } ]
++ zipTwoLists' (inc n) ++ zipTwoLists' (n + 1)
else []; else [];
in zipTwoLists' 0; in zipTwoLists' 0;
@ -227,4 +223,19 @@ in rec {
crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f]; crossLists = f: foldl (fs: args: concatMap (f: map f args) fs) [f];
# Remove duplicate elements from the list
unique = list:
if list == [] then
[]
else
let
x = head list;
xs = unique (drop 1 list);
in [x] ++ remove x xs;
# Intersects list 'e' and another list
intersectLists = e: filter (x: elem x e);
# Subtracts list 'e' from another list
subtractLists = e: filter (x: !(elem x e));
} }

View File

@ -5,7 +5,10 @@
alphabetically sorted. */ alphabetically sorted. */
_1126 = "Christian Lask <mail@elfsechsundzwanzig.de>"; _1126 = "Christian Lask <mail@elfsechsundzwanzig.de>";
abaldeau = "Andreas Baldeau <andreas@baldeau.net>";
abbradar = "Nikolay Amiantov <ab@fmap.me>";
aforemny = "Alexander Foremny <alexanderforemny@googlemail.com>"; aforemny = "Alexander Foremny <alexanderforemny@googlemail.com>";
aherrmann = "Andreas Herrmann <andreash87@gmx.ch>";
ak = "Alexander Kjeldaas <ak@formalprivacy.com>"; ak = "Alexander Kjeldaas <ak@formalprivacy.com>";
akc = "Anders Claesson <akc@akc.is>"; akc = "Anders Claesson <akc@akc.is>";
algorith = "Dries Van Daele <dries_van_daele@telenet.be>"; algorith = "Dries Van Daele <dries_van_daele@telenet.be>";
@ -15,52 +18,100 @@
AndersonTorres = "Anderson Torres <torres.anderson.85@gmail.com>"; AndersonTorres = "Anderson Torres <torres.anderson.85@gmail.com>";
andres = "Andres Loeh <ksnixos@andres-loeh.de>"; andres = "Andres Loeh <ksnixos@andres-loeh.de>";
antono = "Antono Vasiljev <self@antono.info>"; antono = "Antono Vasiljev <self@antono.info>";
ardumont = "Antoine R. Dumont <eniotna.t@gmail.com>";
aristid = "Aristid Breitkreuz <aristidb@gmail.com>";
arobyn = "Alexei Robyn <shados@shados.net>"; arobyn = "Alexei Robyn <shados@shados.net>";
asppsa = "Alastair Pharo <asppsa@gmail.com>";
astsmtl = "Alexander Tsamutali <astsmtl@yandex.ru>"; astsmtl = "Alexander Tsamutali <astsmtl@yandex.ru>";
aszlig = "aszlig <aszlig@redmoonstudios.org>"; aszlig = "aszlig <aszlig@redmoonstudios.org>";
auntie = "Jonathan Glines <auntieNeo@gmail.com>"; auntie = "Jonathan Glines <auntieNeo@gmail.com>";
aycanirican = "Aycan iRiCAN <iricanaycan@gmail.com>"; aycanirican = "Aycan iRiCAN <iricanaycan@gmail.com>";
balajisivaraman = "Balaji Sivaraman<sivaraman.balaji@gmail.com>";
bbenoist = "Baptist BENOIST <return_0@live.com>"; bbenoist = "Baptist BENOIST <return_0@live.com>";
bcdarwin = "Ben Darwin <bcdarwin@gmail.com>";
bdimcheff = "Brandon Dimcheff <brandon@dimcheff.com>";
bennofs = "Benno Fünfstück <benno.fuenfstueck@gmail.com>"; bennofs = "Benno Fünfstück <benno.fuenfstueck@gmail.com>";
benley = "Benjamin Staffin <benley@gmail.com>";
berdario = "Dario Bertini <berdario@gmail.com>"; berdario = "Dario Bertini <berdario@gmail.com>";
bergey = "Daniel Bergey <bergey@teallabs.org>"; bergey = "Daniel Bergey <bergey@teallabs.org>";
bjg = "Brian Gough <bjg@gnu.org>"; bjg = "Brian Gough <bjg@gnu.org>";
bjornfor = "Bjørn Forsman <bjorn.forsman@gmail.com>"; bjornfor = "Bjørn Forsman <bjorn.forsman@gmail.com>";
bluescreen303 = "Mathijs Kwik <mathijs@bluescreen303.nl>"; bluescreen303 = "Mathijs Kwik <mathijs@bluescreen303.nl>";
bobvanderlinden = "Bob van der Linden <bobvanderlinden@gmail.com>";
bodil = "Bodil Stokke <nix@bodil.org>"; bodil = "Bodil Stokke <nix@bodil.org>";
boothead = "Ben Ford <ben@perurbis.com>";
bosu = "Boris Sukholitko <boriss@gmail.com>"; bosu = "Boris Sukholitko <boriss@gmail.com>";
bstrik = "Berno Strik <dutchman55@gmx.com>";
calrama = "Moritz Maxeiner <moritz@ucworks.org>"; calrama = "Moritz Maxeiner <moritz@ucworks.org>";
campadrenalin = "Philip Horger <campadrenalin@gmail.com>"; campadrenalin = "Philip Horger <campadrenalin@gmail.com>";
cdepillabout = "Dennis Gosnell <cdep.illabout@gmail.com>";
cfouche = "Chaddaï Fouché <chaddai.fouche@gmail.com>"; cfouche = "Chaddaï Fouché <chaddai.fouche@gmail.com>";
chaoflow = "Florian Friesdorf <flo@chaoflow.net>"; chaoflow = "Florian Friesdorf <flo@chaoflow.net>";
christopherpoole = "Christopher Mark Poole <mail@christopherpoole.net>";
coconnor = "Corey O'Connor <coreyoconnor@gmail.com>"; coconnor = "Corey O'Connor <coreyoconnor@gmail.com>";
cocreature = "Moritz Kiefer <moritz.kiefer@purelyfunctional.org>";
codyopel = "Cody Opel <codyopel@gmail.com>";
copumpkin = "Dan Peebles <pumpkingod@gmail.com>";
coroa = "Jonas Hörsch <jonas@chaoflow.net>"; coroa = "Jonas Hörsch <jonas@chaoflow.net>";
cstrahan = "Charles Strahan <charles.c.strahan@gmail.com>"; cstrahan = "Charles Strahan <charles.c.strahan@gmail.com>";
cwoac = "Oliver Matthews <oliver@codersoffortune.net>";
DamienCassou = "Damien Cassou <damien.cassou@gmail.com>"; DamienCassou = "Damien Cassou <damien.cassou@gmail.com>";
davidrusu = "David Rusu <davidrusu.me@gmail.com>";
dbohdan = "Danyil Bohdan <danyil.bohdan@gmail.com>";
DerGuteMoritz = "Moritz Heidkamp <moritz@twoticketsplease.de>";
devhell = "devhell <\"^\"@regexmail.net>";
dmalikov = "Dmitry Malikov <malikov.d.y@gmail.com>";
doublec = "Chris Double <chris.double@double.co.nz>"; doublec = "Chris Double <chris.double@double.co.nz>";
ederoyd46 = "Matthew Brown <matt@ederoyd.co.uk>"; ederoyd46 = "Matthew Brown <matt@ederoyd.co.uk>";
eduarrrd = "Eduard Bachmakov <e.bachmakov@gmail.com>";
edwtjo = "Edward Tjörnhammar <ed@cflags.cc>"; edwtjo = "Edward Tjörnhammar <ed@cflags.cc>";
eelco = "Eelco Dolstra <eelco.dolstra@logicblox.com>"; eelco = "Eelco Dolstra <eelco.dolstra@logicblox.com>";
eikek = "Eike Kettner <eike.kettner@posteo.de>";
ellis = "Ellis Whitehead <nixos@ellisw.net>";
emery = "Emery Hemingway <emery@vfemail.net>"; emery = "Emery Hemingway <emery@vfemail.net>";
ertes = "Ertugrul Söylemez <ertesx@gmx.de>"; ertes = "Ertugrul Söylemez <ertesx@gmx.de>";
exlevan = "Alexey Levan <exlevan@gmail.com>";
falsifian = "James Cook <james.cook@utoronto.ca>"; falsifian = "James Cook <james.cook@utoronto.ca>";
flosse = "Markus Kohlhase <mail@markus-kohlhase.de>"; flosse = "Markus Kohlhase <mail@markus-kohlhase.de>";
fluffynukeit = "Daniel Austin <dan@fluffynukeit.com>";
fpletz = "Franz Pletz <fpletz@fnordicwalking.de>";
ftrvxmtrx = "Siarhei Zirukin <ftrvxmtrx@gmail.com>";
funfunctor = "Edward O'Callaghan <eocallaghan@alterapraxis.com>"; funfunctor = "Edward O'Callaghan <eocallaghan@alterapraxis.com>";
fuuzetsu = "Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>"; fuuzetsu = "Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>";
gal_bolle = "Florent Becker <florent.becker@ens-lyon.org>";
garbas = "Rok Garbas <rok@garbas.si>"; garbas = "Rok Garbas <rok@garbas.si>";
garrison = "Jim Garrison <jim@garrison.cc>";
gavin = "Gavin Rogers <gavin@praxeology.co.uk>";
gebner = "Gabriel Ebner <gebner@gebner.org>";
giogadi = "Luis G. Torres <lgtorres42@gmail.com>";
globin = "Robin Gloster <robin@glob.in>";
goibhniu = "Cillian de Róiste <cillian.deroiste@gmail.com>"; goibhniu = "Cillian de Róiste <cillian.deroiste@gmail.com>";
gridaphobe = "Eric Seidel <eric@seidel.io>";
guibert = "David Guibert <david.guibert@gmail.com>"; guibert = "David Guibert <david.guibert@gmail.com>";
henrytill = "Henry Till <henrytill@gmail.com>";
hinton = "Tom Hinton <t@larkery.com>"; hinton = "Tom Hinton <t@larkery.com>";
hrdinka = "Christoph Hrdinka <c.nix@hrdinka.at>"; hrdinka = "Christoph Hrdinka <c.nix@hrdinka.at>";
iand675 = "Ian Duncan <ian@iankduncan.com>";
ianwookim = "Ian-Woo Kim <ianwookim@gmail.com>"; ianwookim = "Ian-Woo Kim <ianwookim@gmail.com>";
iElectric = "Domen Kozar <domen@dev.si>"; iElectric = "Domen Kozar <domen@dev.si>";
iyzsong = "Song Wenwu <iyzsong@gmail.com>"; iyzsong = "Song Wenwu <iyzsong@gmail.com>";
j-keck = "Jürgen Keck <jhyphenkeck@gmail.com>";
jagajaga = "Arseniy Seroka <ars.seroka@gmail.com>";
jb55 = "William Casarin <bill@casarin.me>";
jcumming = "Jack Cummings <jack@mudshark.org>"; jcumming = "Jack Cummings <jack@mudshark.org>";
jgeerds = "Jascha Geerds <jg@ekby.de>"; jgeerds = "Jascha Geerds <jg@ekby.de>";
jirkamarsik = "Jirka Marsik <jiri.marsik89@gmail.com>";
joachifm = "Joachim Fasting <joachifm@fastmail.fm>";
joamaki = "Jussi Maki <joamaki@gmail.com>"; joamaki = "Jussi Maki <joamaki@gmail.com>";
joelmo = "Joel Moberg <joel.moberg@gmail.com>";
joelteon = "Joel Taylor <me@joelt.io>"; joelteon = "Joel Taylor <me@joelt.io>";
jpbernardy = "Jean-Philippe Bernardy <jeanphilippe.bernardy@gmail.com>";
jwiegley = "John Wiegley <johnw@newartisans.com>"; jwiegley = "John Wiegley <johnw@newartisans.com>";
jzellner = "Jeff Zellner <jeffz@eml.cc>";
kkallio = "Karn Kallio <tierpluspluslists@gmail.com>"; kkallio = "Karn Kallio <tierpluspluslists@gmail.com>";
koral = "Koral <koral@mailoo.org>";
kovirobi = "Kovacsics Robert <kovirobi@gmail.com>";
kragniz = "Louis Taylor <kragniz@gmail.com>";
ktosiek = "Tomasz Kontusz <tomasz.kontusz@gmail.com>"; ktosiek = "Tomasz Kontusz <tomasz.kontusz@gmail.com>";
lethalman = "Luca Bruno <lucabru@src.gnome.org>"; lethalman = "Luca Bruno <lucabru@src.gnome.org>";
lhvwb = "Nathaniel Baxter <nathaniel.baxter@gmail.com>"; lhvwb = "Nathaniel Baxter <nathaniel.baxter@gmail.com>";
@ -68,63 +119,109 @@
lovek323 = "Jason O'Conal <jason@oconal.id.au>"; lovek323 = "Jason O'Conal <jason@oconal.id.au>";
ludo = "Ludovic Courtès <ludo@gnu.org>"; ludo = "Ludovic Courtès <ludo@gnu.org>";
madjar = "Georges Dubus <georges.dubus@compiletoi.net>"; madjar = "Georges Dubus <georges.dubus@compiletoi.net>";
magnetophon = "Bart Brouns <bart@magnetophon.nl>";
malyn = "Michael Alyn Miller <malyn@strangeGizmo.com>";
manveru = "Michael Fellinger <m.fellinger@gmail.com>"; manveru = "Michael Fellinger <m.fellinger@gmail.com>";
marcweber = "Marc Weber <marco-oweber@gmx.de>"; marcweber = "Marc Weber <marco-oweber@gmx.de>";
matejc = "Matej Cotman <cotman.matej@gmail.com>"; matejc = "Matej Cotman <cotman.matej@gmail.com>";
matthiasbeyer = "Matthias Beyer <mail@beyermatthias.de>";
meditans = "Carlo Nucera <meditans@gmail.com>";
meisternu = "Matt Miemiec <meister@krutt.org>"; meisternu = "Matt Miemiec <meister@krutt.org>";
michelk = "Michel Kuhlmann <michel@kuhlmanns.info>";
modulistic = "Pablo Costa <modulistic@gmail.com>"; modulistic = "Pablo Costa <modulistic@gmail.com>";
mornfall = "Petr Ročkai <me@mornfall.net>"; mornfall = "Petr Ročkai <me@mornfall.net>";
MP2E = "Cray Elliott <MP2E@archlinux.us>"; MP2E = "Cray Elliott <MP2E@archlinux.us>";
msackman = "Matthew Sackman <matthew@wellquite.org>"; msackman = "Matthew Sackman <matthew@wellquite.org>";
mtreskin = "Max Treskin <zerthurd@gmail.com>";
muflax = "Stefan Dorn <mail@muflax.com>";
nathan-gs = "Nathan Bijnens <nathan@nathan.gs>"; nathan-gs = "Nathan Bijnens <nathan@nathan.gs>";
nckx = "Tobias Geerinckx-Rice <tobias.geerinckx.rice@gmail.com>";
notthemessiah = "Brian Cohen <brian.cohen.88@gmail.com>"; notthemessiah = "Brian Cohen <brian.cohen.88@gmail.com>";
np = "Nicolas Pouillard <np.nix@nicolaspouillard.fr>";
nslqqq = "Nikita Mikhailov <nslqqq@gmail.com>";
obadz = "obadz <dav-nixos@odav.org>";
ocharles = "Oliver Charles <ollie@ocharles.org.uk>"; ocharles = "Oliver Charles <ollie@ocharles.org.uk>";
offline = "Jaka Hudoklin <jakahudoklin@gmail.com>"; offline = "Jaka Hudoklin <jakahudoklin@gmail.com>";
olcai = "Erik Timan <dev@timan.info>";
orbitz = "Malcolm Matalka <mmatalka@gmail.com>"; orbitz = "Malcolm Matalka <mmatalka@gmail.com>";
page = "Carles Pagès <page@cubata.homelinux.net>"; page = "Carles Pagès <page@cubata.homelinux.net>";
paholg = "Paho Lurie-Gregg <paho@paholg.com>";
pakhfn = "Fedor Pakhomov <pakhfn@gmail.com>";
pashev = "Igor Pashev <pashev.igor@gmail.com>";
phausmann = "Philipp Hausmann <nix@314.ch>";
phreedom = "Evgeny Egorochkin <phreedom@yandex.ru>"; phreedom = "Evgeny Egorochkin <phreedom@yandex.ru>";
pierron = "Nicolas B. Pierron <nixos@nbp.name>"; pierron = "Nicolas B. Pierron <nixos@nbp.name>";
piotr = "Piotr Pietraszkiewicz <ppietrasa@gmail.com>"; piotr = "Piotr Pietraszkiewicz <ppietrasa@gmail.com>";
pjones = "Peter Jones <pjones@devalot.com>";
pkmx = "Chih-Mao Chen <pkmx.tw@gmail.com>"; pkmx = "Chih-Mao Chen <pkmx.tw@gmail.com>";
plcplc = "Philip Lykke Carlsen <plcplc@gmail.com>"; plcplc = "Philip Lykke Carlsen <plcplc@gmail.com>";
pmahoney = "Patrick Mahoney <pat@polycrystal.org>";
prikhi = "Pavan Rikhi <pavan.rikhi@gmail.com>";
pSub = "Pascal Wittmann <mail@pascal-wittmann.de>"; pSub = "Pascal Wittmann <mail@pascal-wittmann.de>";
puffnfresh = "Brian McKenna <brian@brianmckenna.org>";
qknight = "Joachim Schiele <js@lastlog.de>"; qknight = "Joachim Schiele <js@lastlog.de>";
ragge = "Ragnar Dahlen <r.dahlen@gmail.com>";
raskin = "Michael Raskin <7c6f434c@mail.ru>"; raskin = "Michael Raskin <7c6f434c@mail.ru>";
redbaron = "Maxim Ivanov <ivanov.maxim@gmail.com>"; redbaron = "Maxim Ivanov <ivanov.maxim@gmail.com>";
refnil = "Martin Lavoie <broemartino@gmail.com>"; refnil = "Martin Lavoie <broemartino@gmail.com>";
relrod = "Ricky Elrod <ricky@elrod.me>"; relrod = "Ricky Elrod <ricky@elrod.me>";
renzo = "Renzo Carbonara <renzocarbonara@gmail.com>";
rickynils = "Rickard Nilsson <rickynils@gmail.com>"; rickynils = "Rickard Nilsson <rickynils@gmail.com>";
rob = "Rob Vermaas <rob.vermaas@gmail.com>"; rob = "Rob Vermaas <rob.vermaas@gmail.com>";
robberer = "Longrin Wischnewski <robberer@freakmail.de>";
roconnor = "Russell O'Connor <roconnor@theorem.ca>"; roconnor = "Russell O'Connor <roconnor@theorem.ca>";
roelof = "Roelof Wobben <rwobben@hotmail.com>"; roelof = "Roelof Wobben <rwobben@hotmail.com>";
romildo = "José Romildo Malaquias <malaquias@gmail.com>"; romildo = "José Romildo Malaquias <malaquias@gmail.com>";
rszibele = "Richard Szibele <richard_szibele@hotmail.com>"; rszibele = "Richard Szibele <richard_szibele@hotmail.com>";
rushmorem = "Rushmore Mushambi <rushmore@webenchanter.com>";
rycee = "Robert Helgesson <robert@rycee.net>";
sander = "Sander van der Burg <s.vanderburg@tudelft.nl>"; sander = "Sander van der Burg <s.vanderburg@tudelft.nl>";
schmitthenner = "Fabian Schmitthenner <development@schmitthenner.eu>";
schristo = "Scott Christopher <schristopher@konputa.com>";
sepi = "Raffael Mancini <raffael@mancini.lu>";
shell = "Shell Turner <cam.turn@gmail.com>";
shlevy = "Shea Levy <shea@shealevy.com>"; shlevy = "Shea Levy <shea@shealevy.com>";
simons = "Peter Simons <simons@cryp.to>"; simons = "Peter Simons <simons@cryp.to>";
sjagoe = "Simon Jagoe <simon@simonjagoe.com>";
sjmackenzie = "Stewart Mackenzie <setori88@gmail.com>";
skeidel = "Sven Keidel <svenkeidel@gmail.com>"; skeidel = "Sven Keidel <svenkeidel@gmail.com>";
smironov = "Sergey Mironov <ierton@gmail.com>"; smironov = "Sergey Mironov <ierton@gmail.com>";
sprock = "Roger Mason <rmason@mun.ca>"; sprock = "Roger Mason <rmason@mun.ca>";
spwhitt = "Spencer Whitt <sw@swhitt.me>";
sztupi = "Attila Sztupak <attila.sztupak@gmail.com>";
tailhook = "Paul Colomiets <paul@colomiets.name>"; tailhook = "Paul Colomiets <paul@colomiets.name>";
thammers = "Tobias Hammerschmidt <jawr@gmx.de>"; thammers = "Tobias Hammerschmidt <jawr@gmx.de>";
the-kenny = "Moritz Ulrich <moritz@tarn-vedra.de>"; the-kenny = "Moritz Ulrich <moritz@tarn-vedra.de>";
theuni = "Christian Theune <ct@flyingcircus.io>";
thoughtpolice = "Austin Seipp <aseipp@pobox.com>"; thoughtpolice = "Austin Seipp <aseipp@pobox.com>";
titanous = "Jonathan Rudenberg <jonathan@titanous.com>";
tomberek = "Thomas Bereknyei <tomberek@gmail.com>"; tomberek = "Thomas Bereknyei <tomberek@gmail.com>";
trino = "Hubert Mühlhans <muehlhans.hubert@ekodia.de>";
tstrobel = "Thomas Strobel <ts468@cam.ac.uk>";
ttuegel = "Thomas Tuegel <ttuegel@gmail.com>"; ttuegel = "Thomas Tuegel <ttuegel@gmail.com>";
tv = "Tomislav Viljetić <tv@shackspace.de>"; tv = "Tomislav Viljetić <tv@shackspace.de>";
twey = "James Twey Kay <twey@twey.co.uk>";
urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>"; urkud = "Yury G. Kudryashov <urkud+nix@ya.ru>";
vandenoever = "Jos van den Oever <jos@vandenoever.info>";
vbgl = "Vincent Laporte <Vincent.Laporte@gmail.com>";
vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>"; vbmithr = "Vincent Bernardoff <vb@luminar.eu.org>";
vcunat = "Vladimír Čunát <vcunat@gmail.com>"; vcunat = "Vladimír Čunát <vcunat@gmail.com>";
viric = "Lluís Batlle i Rossell <viric@viric.name>"; viric = "Lluís Batlle i Rossell <viric@viric.name>";
vizanto = "Danny Wilson <danny@prime.vc>"; vizanto = "Danny Wilson <danny@prime.vc>";
vlstill = "Vladimír Štill <xstill@fi.muni.cz>"; vlstill = "Vladimír Štill <xstill@fi.muni.cz>";
vmandela = "Venkateswara Rao Mandela <venkat.mandela@gmail.com>";
vozz = "Oliver Hunt <oliver.huntuk@gmail.com>";
winden = "Antonio Vargas Gonzalez <windenntw@gmail.com>"; winden = "Antonio Vargas Gonzalez <windenntw@gmail.com>";
wizeman = "Ricardo M. Correia <rcorreia@wizy.org>"; wizeman = "Ricardo M. Correia <rcorreia@wizy.org>";
wjlroe = "William Roe <willroe@gmail.com>"; wjlroe = "William Roe <willroe@gmail.com>";
wkennington = "William A. Kennington III <william@wkennington.com>"; wkennington = "William A. Kennington III <william@wkennington.com>";
wmertens = "Wout Mertens <Wout.Mertens@gmail.com>"; wmertens = "Wout Mertens <Wout.Mertens@gmail.com>";
wscott = "Wayne Scott <wsc9tt@gmail.com>";
wyvie = "Elijah Rum <elijahrum@gmail.com>";
yarr = "Dmitry V. <savraz@gmail.com>";
z77z = "Marco Maggesi <maggesi@math.unifi.it>"; z77z = "Marco Maggesi <maggesi@math.unifi.it>";
zef = "Zef Hemel <zef@zef.me>"; zef = "Zef Hemel <zef@zef.me>";
zimbatm = "zimbatm <zimbatm@zimbatm.com>"; zimbatm = "zimbatm <zimbatm@zimbatm.com>";
zoomulator = "Kim Simmons <zoomulator@gmail.com>"; zoomulator = "Kim Simmons <zoomulator@gmail.com>";
Gonzih = "Max Gonzih <gonzih@gmail.com>";
} }

View File

@ -1,5 +1,5 @@
let lib = import ./default.nix; let lib = import ./default.nix;
inherit (builtins) isFunction hasAttr getAttr head tail isList isAttrs isInt attrNames; inherit (builtins) isFunction head tail isList isAttrs isInt attrNames;
in in
@ -61,7 +61,7 @@ rec {
fun = n : x : fun = n : x :
let newArgs = fixed : let newArgs = fixed :
let args = takeFixed fixed; let args = takeFixed fixed;
mergeFun = getAttr n args; mergeFun = args.${n};
in if isAttrs x then (mergeFun args x) in if isAttrs x then (mergeFun args x)
else assert isFunction x; else assert isFunction x;
mergeFun args (x ( args // { inherit fixed; })); mergeFun args (x ( args // { inherit fixed; }));
@ -102,15 +102,12 @@ rec {
# } # }
composedArgsAndFun = f: foldArgs defaultMerge f {}; composedArgsAndFun = f: foldArgs defaultMerge f {};
# shortcut for attrByPath ["name"] default attrs
maybeAttrNullable = name: default: attrs:
if attrs == null then default else
if __hasAttr name attrs then (__getAttr name attrs) else default;
# shortcut for attrByPath ["name"] default attrs # shortcut for attrByPath ["name"] default attrs
maybeAttr = name: default: attrs: maybeAttrNullable = maybeAttr;
if __hasAttr name attrs then (__getAttr name attrs) else default;
# shortcut for attrByPath ["name"] default attrs
maybeAttr = name: default: attrs: attrs.${name} or default;
# Return the second argument if the first one is true or the empty version # Return the second argument if the first one is true or the empty version
@ -233,7 +230,7 @@ rec {
closePropagation = list: (uniqList {inputList = (innerClosePropagation [] list);}); closePropagation = list: (uniqList {inputList = (innerClosePropagation [] list);});
# calls a function (f attr value ) for each record item. returns a list # calls a function (f attr value ) for each record item. returns a list
mapAttrsFlatten = f : r : map (attr: f attr (builtins.getAttr attr r) ) (attrNames r); mapAttrsFlatten = f : r : map (attr: f attr r.${attr}) (attrNames r);
# attribute set containing one attribute # attribute set containing one attribute
nvs = name : value : listToAttrs [ (nameValuePair name value) ]; nvs = name : value : listToAttrs [ (nameValuePair name value) ];
@ -250,10 +247,10 @@ rec {
# merge attributes with custom function handling the case that the attribute # merge attributes with custom function handling the case that the attribute
# exists in both sets # exists in both sets
mergeAttrsWithFunc = f : set1 : set2 : mergeAttrsWithFunc = f : set1 : set2 :
fold (n: set : if (__hasAttr n set) fold (n: set : if set ? ${n}
then setAttr set n (f (__getAttr n set) (__getAttr n set2)) then setAttr set n (f set.${n} set2.${n})
else set ) else set )
(set2 // set1) (__attrNames set2); (set2 // set1) (attrNames set2);
# merging two attribute set concatenating the values of same attribute names # merging two attribute set concatenating the values of same attribute names
# eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; } # eg { a = 7; } { a = [ 2 3 ]; } becomes { a = [ 7 2 3 ]; }
@ -270,15 +267,15 @@ rec {
overrideSnd ? [ "buildPhase" ] overrideSnd ? [ "buildPhase" ]
} : attrs1 : attrs2 : } : attrs1 : attrs2 :
fold (n: set : fold (n: set :
setAttr set n ( if (__hasAttr n set) setAttr set n ( if set ? ${n}
then # merge then # merge
if elem n mergeLists # attribute contains list, merge them by concatenating if elem n mergeLists # attribute contains list, merge them by concatenating
then (__getAttr n attrs2) ++ (__getAttr n attrs1) then attrs2.${n} ++ attrs1.${n}
else if elem n overrideSnd else if elem n overrideSnd
then __getAttr n attrs1 then attrs1.${n}
else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined" else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
else __getAttr n attrs2 # add attribute not existing in attr1 else attrs2.${n} # add attribute not existing in attr1
)) attrs1 (__attrNames attrs2); )) attrs1 (attrNames attrs2);
# example usage: # example usage:
@ -300,14 +297,14 @@ rec {
fold lib.mergeAttrs {} [ fold lib.mergeAttrs {} [
x y x y
(mapAttrs ( a : v : # merge special names using given functions (mapAttrs ( a : v : # merge special names using given functions
if (hasAttr a x) if x ? ${a}
then if (hasAttr a y) then if y ? ${a}
then v (getAttr a x) (getAttr a y) # both have attr, use merge func then v x.${a} y.${a} # both have attr, use merge func
else (getAttr a x) # only x has attr else x.${a} # only x has attr
else (getAttr a y) # only y has attr) else y.${a} # only y has attr)
) (removeAttrs mergeAttrBy2 ) (removeAttrs mergeAttrBy2
# don't merge attrs which are neither in x nor y # don't merge attrs which are neither in x nor y
(filter (a : (! hasAttr a x) && (! hasAttr a y) ) (filter (a: ! x ? ${a} && ! y ? ${a})
(attrNames mergeAttrBy2)) (attrNames mergeAttrBy2))
) )
) )
@ -403,7 +400,7 @@ rec {
// args2.cfg; // args2.cfg;
opts = attrValues (mapAttrs (a : v : opts = attrValues (mapAttrs (a : v :
let v2 = if v ? set || v ? unset then v else { set = v; }; let v2 = if v ? set || v ? unset then v else { set = v; };
n = if (getAttr (flagName a) cfgWithDefaults) then "set" else "unset"; n = if cfgWithDefaults.${flagName a} then "set" else "unset";
attr = maybeAttr n {} v2; in attr = maybeAttr n {} v2; in
if (maybeAttr "assertion" true attr) if (maybeAttr "assertion" true attr)
then attr then attr

View File

@ -9,28 +9,72 @@ rec {
/* Evaluate a set of modules. The result is a set of two /* Evaluate a set of modules. The result is a set of two
attributes: options: the nested set of all option declarations, attributes: options: the nested set of all option declarations,
and config: the nested set of all option values. */ and config: the nested set of all option values.
evalModules = { modules, prefix ? [], args ? {}, check ? true }: !!! Please think twice before adding to this argument list! The more
that is specified here instead of in the modules themselves the harder
it is to transparently move a set of modules to be a submodule of another
config (as the proper arguments need to be replicated at each call to
evalModules) and the less declarative the module set is. */
evalModules = { modules
, prefix ? []
, # This would be remove in the future, Prefer _module.args option instead.
args ? {}
, # This would be remove in the future, Prefer _module.check option instead.
check ? true
}:
let let
args' = args // { lib = import ./.; } // result; # This internal module declare internal options under the `_module'
closed = closeModules modules args'; # attribute. These options are fragile, as they are used by the
# module system to change the interpretation of modules.
internalModule = rec {
_file = ./modules.nix;
key = _file;
options = {
_module.args = mkOption {
type = types.attrsOf types.unspecified;
internal = true;
description = "Arguments passed to each module.";
};
_module.check = mkOption {
type = types.uniq types.bool;
internal = true;
default = check;
description = "Whether to check whether all option definitions have matching declarations.";
};
};
config = {
_module.args = args;
};
};
closed = closeModules (modules ++ [ internalModule ]) { inherit config options; lib = import ./.; };
# Note: the list of modules is reversed to maintain backward # Note: the list of modules is reversed to maintain backward
# compatibility with the old module system. Not sure if this is # compatibility with the old module system. Not sure if this is
# the most sensible policy. # the most sensible policy.
options = mergeModules prefix (reverseList closed); options = mergeModules prefix (reverseList closed);
# Traverse options and extract the option values into the final # Traverse options and extract the option values into the final
# config set. At the same time, check whether all option # config set. At the same time, check whether all option
# definitions have matching declarations. # definitions have matching declarations.
# !!! _module.check's value can't depend on any other config values
# without an infinite recursion. One way around this is to make the
# 'config' passed around to the modules be unconditionally unchecked,
# and only do the check in 'result'.
config = yieldConfig prefix options; config = yieldConfig prefix options;
yieldConfig = prefix: set: yieldConfig = prefix: set:
let res = removeAttrs (mapAttrs (n: v: let res = removeAttrs (mapAttrs (n: v:
if isOption v then v.value if isOption v then v.value
else yieldConfig (prefix ++ [n]) v) set) ["_definedNames"]; else yieldConfig (prefix ++ [n]) v) set) ["_definedNames"];
in in
if check && set ? _definedNames then if options._module.check.value && set ? _definedNames then
fold (m: res: fold (m: res:
fold (name: res: fold (name: res:
if hasAttr name set then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.") if set ? ${name} then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.")
res m.names) res m.names)
res set._definedNames res set._definedNames
else else
@ -43,7 +87,7 @@ rec {
let let
toClosureList = file: parentKey: imap (n: x: toClosureList = file: parentKey: imap (n: x:
if isAttrs x || isFunction x then if isAttrs x || isFunction x then
unifyModuleSyntax file "${parentKey}:anon-${toString n}" (applyIfFunction x args) unifyModuleSyntax file "${parentKey}:anon-${toString n}" (unpackSubmodule applyIfFunction x args)
else else
unifyModuleSyntax (toString x) (toString x) (applyIfFunction (import x) args)); unifyModuleSyntax (toString x) (toString x) (applyIfFunction (import x) args));
in in
@ -58,7 +102,7 @@ rec {
if m ? config || m ? options then if m ? config || m ? options then
let badAttrs = removeAttrs m ["imports" "options" "config" "key" "_file"]; in let badAttrs = removeAttrs m ["imports" "options" "config" "key" "_file"]; in
if badAttrs != {} then if badAttrs != {} then
throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'." throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'. This is caused by assignments to the top-level attributes `config' or `options'."
else else
{ file = m._file or file; { file = m._file or file;
key = toString m.key or key; key = toString m.key or key;
@ -74,7 +118,39 @@ rec {
config = removeAttrs m ["key" "_file" "require" "imports"]; config = removeAttrs m ["key" "_file" "require" "imports"];
}; };
applyIfFunction = f: arg: if isFunction f then f arg else f; applyIfFunction = f: arg@{ config, options, lib }: if isFunction f then
let
# Module arguments are resolved in a strict manner when attribute set
# deconstruction is used. As the arguments are now defined with the
# config._module.args option, the strictness used on the attribute
# set argument would cause an infinite loop, if the result of the
# option is given as argument.
#
# To work-around the strictness issue on the deconstruction of the
# attributes set argument, we create a new attribute set which is
# constructed to satisfy the expected set of attributes. Thus calling
# a module will resolve strictly the attributes used as argument but
# not their values. The values are forwarding the result of the
# evaluation of the option.
requiredArgs = builtins.attrNames (builtins.functionArgs f);
extraArgs = builtins.listToAttrs (map (name: {
inherit name;
value = config._module.args.${name};
}) requiredArgs);
in f (extraArgs // arg)
else
f;
/* We have to pack and unpack submodules. We cannot wrap the expected
result of the function as we would no longer be able to list the arguments
of the submodule. (see applyIfFunction) */
unpackSubmodule = unpack: m: args:
if isType "submodule" m then
{ _file = m.file; } // (unpack m.submodule args)
else unpack m args;
packSubmodule = file: m:
{ _type = "submodule"; file = file; submodule = m; };
/* Merge a list of modules. This will recurse over the option /* Merge a list of modules. This will recurse over the option
declarations in all modules, combining them into a single set. declarations in all modules, combining them into a single set.
@ -94,24 +170,21 @@ rec {
loc = prefix ++ [name]; loc = prefix ++ [name];
# Get all submodules that declare name. # Get all submodules that declare name.
decls = concatLists (map (m: decls = concatLists (map (m:
if hasAttr name m.options if m.options ? ${name}
then [ { inherit (m) file; options = getAttr name m.options; } ] then [ { inherit (m) file; options = m.options.${name}; } ]
else [] else []
) options); ) options);
# Get all submodules that define name. # Get all submodules that define name.
defns = concatLists (map (m: defns = concatLists (map (m:
if hasAttr name m.config if m.config ? ${name}
then map (config: { inherit (m) file; inherit config; }) then map (config: { inherit (m) file; inherit config; })
(pushDownProperties (getAttr name m.config)) (pushDownProperties m.config.${name})
else [] else []
) configs); ) configs);
nrOptions = count (m: isOption m.options) decls; nrOptions = count (m: isOption m.options) decls;
# Process mkMerge and mkIf properties. # Extract the definitions for this loc
defns' = concatMap (m: defns' = map (m: { inherit (m) file; value = m.config.${name}; })
if hasAttr name m.config (filter (m: m.config ? ${name}) configs);
then map (m': { inherit (m) file; value = m'; }) (dischargeProperties (getAttr name m.config))
else []
) configs;
in in
if nrOptions == length decls then if nrOptions == length decls then
let opt = fixupOptionType loc (mergeOptionDecls loc decls); let opt = fixupOptionType loc (mergeOptionDecls loc decls);
@ -132,20 +205,41 @@ rec {
The exception is the options attribute, which specifies The exception is the options attribute, which specifies
sub-options. These can be specified multiple times to allow one sub-options. These can be specified multiple times to allow one
module to add sub-options to an option declared somewhere else module to add sub-options to an option declared somewhere else
(e.g. multiple modules define sub-options for fileSystems). */ (e.g. multiple modules define sub-options for fileSystems).
'loc' is the list of attribute names where the option is located.
'opts' is a list of modules. Each module has an options attribute which
correspond to the definition of 'loc' in 'opt.file'. */
mergeOptionDecls = loc: opts: mergeOptionDecls = loc: opts:
fold (opt: res: fold (opt: res:
if opt.options ? default && res ? default || if opt.options ? default && res ? default ||
opt.options ? example && res ? example || opt.options ? example && res ? example ||
opt.options ? description && res ? description || opt.options ? description && res ? description ||
opt.options ? apply && res ? apply || opt.options ? apply && res ? apply ||
opt.options ? type && res ? type # Accept to merge options which have identical types.
opt.options ? type && res ? type && opt.options.type.name != res.type.name
then then
throw "The option `${showOption loc}' in `${opt.file}' is already declared in ${showFiles res.declarations}." throw "The option `${showOption loc}' in `${opt.file}' is already declared in ${showFiles res.declarations}."
else else
opt.options // res // let
/* Add the modules of the current option to the list of modules
already collected. The options attribute except either a list of
submodules or a submodule. For each submodule, we add the file of the
current option declaration as the file use for the submodule. If the
submodule defines any filename, then we ignore the enclosing option file. */
options' = toList opt.options.options;
coerceOption = file: opt:
if isFunction opt then packSubmodule file opt
else packSubmodule file { options = opt; };
getSubModules = opt.options.type.getSubModules or null;
submodules =
if getSubModules != null then map (packSubmodule opt.file) getSubModules ++ res.options
else if opt.options ? options then map (coerceOption opt.file) options' ++ res.options
else res.options;
in opt.options // res //
{ declarations = [opt.file] ++ res.declarations; { declarations = [opt.file] ++ res.declarations;
options = if opt.options ? options then [(toList opt.options.options ++ res.options)] else []; options = submodules;
} }
) { inherit loc; declarations = []; options = []; } opts; ) { inherit loc; declarations = []; options = []; } opts;
@ -153,27 +247,17 @@ rec {
config value. */ config value. */
evalOptionValue = loc: opt: defs: evalOptionValue = loc: opt: defs:
let let
# Process mkOverride properties, adding in the default # Add in the default value for this option, if any.
# value specified in the option declaration (if any). defs' = (optional (opt ? default)
defsFinal' = filterOverrides { file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs;
((if opt ? default then [{ file = head opt.declarations; value = mkOptionDefault opt.default; }] else []) ++ defs);
# Sort mkOrder properties. # Handle properties, check types, and merge everything together
defsFinal = inherit (mergeDefinitions loc opt.type defs') isDefined defsFinal mergedValue;
# Avoid sorting if we don't have to.
if any (def: def.value._type or "" == "order") defsFinal'
then sortProperties defsFinal'
else defsFinal';
files = map (def: def.file) defsFinal; files = map (def: def.file) defsFinal;
# Type-check the remaining definitions, and merge them if
# possible.
merged = merged =
if defsFinal == [] then if isDefined then mergedValue
throw "The option `${showOption loc}' is used but not defined." else throw "The option `${showOption loc}' is used but not defined.";
else
fold (def: res:
if opt.type.check def.value then res
else throw "The option value `${showOption loc}' in `${def.file}' is not a ${opt.type.name}.")
(opt.type.merge loc defsFinal) defsFinal;
# Finally, apply the apply function to the merged # Finally, apply the apply function to the merged
# value. This allows options to yield a value computed # value. This allows options to yield a value computed
# from the definitions. # from the definitions.
@ -181,10 +265,42 @@ rec {
in opt // in opt //
{ value = addErrorContext "while evaluating the option `${showOption loc}':" value; { value = addErrorContext "while evaluating the option `${showOption loc}':" value;
definitions = map (def: def.value) defsFinal; definitions = map (def: def.value) defsFinal;
isDefined = defsFinal != []; inherit isDefined files;
inherit files;
}; };
# Merge definitions of a value of a given type
mergeDefinitions = loc: type: defs: rec {
defsFinal =
let
# Process mkMerge and mkIf properties
processIfAndMerge = defs: concatMap (m:
map (value: { inherit (m) file; inherit value; }) (dischargeProperties m.value)
) defs;
# Process mkOverride properties
processOverride = defs: filterOverrides defs;
# Sort mkOrder properties
processOrder = defs:
# Avoid sorting if we don't have to.
if any (def: def.value._type or "" == "order") defs
then sortProperties defs
else defs;
in
processOrder (processOverride (processIfAndMerge defs));
# Type-check the remaining definitions, and merge them
mergedValue = fold (def: res:
if type.check def.value then res
else throw "The option value `${showOption loc}' in `${def.file}' is not a ${type.name}.")
(type.merge loc defsFinal) defsFinal;
isDefined = defsFinal != [];
optionalValue =
if isDefined then { value = mergedValue; }
else {};
};
/* Given a config set, expand mkMerge properties, and push down the /* Given a config set, expand mkMerge properties, and push down the
other properties into the children. The result is a list of other properties into the children. The result is a list of
config sets that do not have properties at top-level. For config sets that do not have properties at top-level. For
@ -254,7 +370,7 @@ rec {
let let
defaultPrio = 100; defaultPrio = 100;
getPrio = def: if def.value._type or "" == "override" then def.value.priority else defaultPrio; getPrio = def: if def.value._type or "" == "override" then def.value.priority else defaultPrio;
min = x: y: if builtins.lessThan x y then x else y; min = x: y: if x < y then x else y;
highestPrio = fold (def: prio: min (getPrio def) prio) 9999 defs; highestPrio = fold (def: prio: min (getPrio def) prio) 9999 defs;
strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def; strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def;
in concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs; in concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs;
@ -273,23 +389,24 @@ rec {
in sort compare defs'; in sort compare defs';
/* Hack for backward compatibility: convert options of type /* Hack for backward compatibility: convert options of type
optionSet to configOf. FIXME: remove eventually. */ optionSet to options of type submodule. FIXME: remove
eventually. */
fixupOptionType = loc: opt: fixupOptionType = loc: opt:
let let
options' = opt.options or options = opt.options or
(throw "Option `${showOption loc'}' has type optionSet but has no option attribute."); (throw "Option `${showOption loc'}' has type optionSet but has no option attribute, in ${showFiles opt.declarations}.");
coerce = x:
if isFunction x then x
else { config, ... }: { options = x; };
options = map coerce (flatten options');
f = tp: f = tp:
if tp.name == "option set" then types.submodule options if tp.name == "option set" || tp.name == "submodule" then
throw "The option ${showOption loc} uses submodules without a wrapping type, in ${showFiles opt.declarations}."
else if tp.name == "attribute set of option sets" then types.attrsOf (types.submodule options) else if tp.name == "attribute set of option sets" then types.attrsOf (types.submodule options)
else if tp.name == "list or attribute set of option sets" then types.loaOf (types.submodule options) else if tp.name == "list or attribute set of option sets" then types.loaOf (types.submodule options)
else if tp.name == "list of option sets" then types.listOf (types.submodule options) else if tp.name == "list of option sets" then types.listOf (types.submodule options)
else if tp.name == "null or option set" then types.nullOr (types.submodule options) else if tp.name == "null or option set" then types.nullOr (types.submodule options)
else tp; else tp;
in opt // { type = f (opt.type or types.unspecified); }; in
if opt.type.getSubModules or null == null
then opt // { type = f (opt.type or types.unspecified); }
else opt // { type = opt.type.substSubModules opt.options; options = []; };
/* Properties. */ /* Properties. */
@ -331,6 +448,31 @@ rec {
mkBefore = mkOrder 500; mkBefore = mkOrder 500;
mkAfter = mkOrder 1500; mkAfter = mkOrder 1500;
# Convenient property used to transfer all definitions and their
# properties from one option to another. This property is useful for
# renaming options, and also for including properties from another module
# system, including sub-modules.
#
# { config, options, ... }:
#
# {
# # 'bar' might not always be defined in the current module-set.
# config.foo.enable = mkAliasDefinitions (options.bar.enable or {});
#
# # 'barbaz' has to be defined in the current module-set.
# config.foobar.paths = mkAliasDefinitions options.barbaz.paths;
# }
#
# Note, this is different than taking the value of the option and using it
# as a definition, as the new definition will not keep the mkOverride /
# mkDefault properties of the previous option.
#
mkAliasDefinitions = mkAliasAndWrapDefinitions id;
mkAliasAndWrapDefinitions = wrap: option:
mkMerge
(optional (isOption option && option.isDefined)
(wrap (mkMerge option.definitions)));
/* Compatibility. */ /* Compatibility. */
fixMergeModules = modules: args: evalModules { inherit modules args; check = false; }; fixMergeModules = modules: args: evalModules { inherit modules args; check = false; };

View File

@ -31,6 +31,23 @@ rec {
type = lib.types.bool; type = lib.types.bool;
}; };
# This option accept anything, but it does not produce any result. This
# is useful for sharing a module across different module sets without
# having to implement similar features as long as the value of the options
# are not expected.
mkSinkUndeclaredOptions = attrs: mkOption ({
internal = true;
visible = false;
default = false;
description = "Sink for option definitions.";
type = mkOptionType {
name = "sink";
check = x: true;
merge = loc: defs: false;
};
apply = x: throw "Option value is not readable because the option is not declared.";
} // attrs);
mergeDefaultOption = loc: defs: mergeDefaultOption = loc: defs:
let list = getValues defs; in let list = getValues defs; in
if length list == 1 then head list if length list == 1 then head list
@ -79,10 +96,11 @@ rec {
declarations = filter (x: x != unknownModule) opt.declarations; declarations = filter (x: x != unknownModule) opt.declarations;
internal = opt.internal or false; internal = opt.internal or false;
visible = opt.visible or true; visible = opt.visible or true;
type = opt.type.name or null;
} }
// optionalAttrs (opt ? example) { example = scrubOptionValue opt.example; } // (if opt ? example then { example = scrubOptionValue opt.example; } else {})
// optionalAttrs (opt ? default) { default = scrubOptionValue opt.default; } // (if opt ? default then { default = scrubOptionValue opt.default; } else {})
// optionalAttrs (opt ? defaultText) { default = opt.defaultText; }; // (if opt ? defaultText then { default = opt.defaultText; } else {});
subOptions = subOptions =
let ss = opt.type.getSubOptions opt.loc; let ss = opt.type.getSubOptions opt.loc;

View File

@ -2,7 +2,7 @@ let lists = import ./lists.nix; in
rec { rec {
gnu = linux; /* ++ hurd ++ kfreebsd ++ ... */ gnu = linux; /* ++ hurd ++ kfreebsd ++ ... */
linux = ["i686-linux" "x86_64-linux" "armv5tel-linux" "armv7l-linux" "mips64el-linux"]; linux = ["i686-linux" "x86_64-linux" "armv5tel-linux" "armv6l-linux" "armv7l-linux" "mips64el-linux"];
darwin = ["x86_64-darwin"]; darwin = ["x86_64-darwin"];
freebsd = ["i686-freebsd" "x86_64-freebsd"]; freebsd = ["i686-freebsd" "x86_64-freebsd"];
openbsd = ["i686-openbsd" "x86_64-openbsd"]; openbsd = ["i686-openbsd" "x86_64-openbsd"];

View File

@ -62,8 +62,8 @@ rec {
in { result = x.result ++ [entry.text] ++ y.result; in { result = x.result ++ [entry.text] ++ y.result;
done = y.done; done = y.done;
} }
else if hasAttr entry done then f done (tail todo) else if done ? ${entry} then f done (tail todo)
else f (done // listToAttrs [{name = entry; value = 1;}]) ([(builtins.getAttr entry predefined)] ++ tail todo); else f (done // listToAttrs [{name = entry; value = 1;}]) ([predefined.${entry}] ++ tail todo);
in (f {} arg).result; in (f {} arg).result;
textClosureMap = f: predefined: names: textClosureMap = f: predefined: names:

View File

@ -2,7 +2,7 @@
let lib = import ./default.nix; let lib = import ./default.nix;
inherit (builtins) add sub lessThan length; inherit (builtins) length;
in in
@ -79,7 +79,7 @@ rec {
stringToCharacters = s: let l = stringLength s; in stringToCharacters = s: let l = stringLength s; in
if l == 0 if l == 0
then [] then []
else map (p: substring p 1 s) (lib.range 0 (sub l 1)); else map (p: substring p 1 s) (lib.range 0 (l - 1));
# Manipulate a string charcater by character and replace them by strings # Manipulate a string charcater by character and replace them by strings
@ -123,7 +123,7 @@ rec {
toUpper = replaceChars lowerChars upperChars; toUpper = replaceChars lowerChars upperChars;
# Appends string context from another string # Appends string context from another string
addContextFrom = a: b: (substring 0 0 a)+b; addContextFrom = a: b: substring 0 0 a + b;
# Compares strings not requiring context equality # Compares strings not requiring context equality
# Obviously, a workaround but works on all Nix versions # Obviously, a workaround but works on all Nix versions
@ -139,18 +139,18 @@ rec {
s = addContextFrom _sep _s; s = addContextFrom _sep _s;
sepLen = stringLength sep; sepLen = stringLength sep;
sLen = stringLength s; sLen = stringLength s;
lastSearch = sub sLen sepLen; lastSearch = sLen - sepLen;
startWithSep = startAt: startWithSep = startAt:
substring startAt sepLen s == sep; substring startAt sepLen s == sep;
recurse = index: startAt: recurse = index: startAt:
let cutUntil = i: [(substring startAt (sub i startAt) s)]; in let cutUntil = i: [(substring startAt (i - startAt) s)]; in
if lessThan index lastSearch then if index < lastSearch then
if startWithSep index then if startWithSep index then
let restartAt = add index sepLen; in let restartAt = index + sepLen; in
cutUntil index ++ recurse restartAt restartAt cutUntil index ++ recurse restartAt restartAt
else else
recurse (add index 1) startAt recurse (index + 1) startAt
else else
cutUntil sLen; cutUntil sLen;
in in
@ -208,4 +208,15 @@ rec {
# standard GNU Autoconf scripts. # standard GNU Autoconf scripts.
enableFeature = enable: feat: "--${if enable then "enable" else "disable"}-${feat}"; enableFeature = enable: feat: "--${if enable then "enable" else "disable"}-${feat}";
# Create a fixed width string with additional prefix to match required width
fixedWidthString = width: filler: str:
let
strw = lib.stringLength str;
reqWidth = width - (lib.stringLength filler);
in
assert strw <= width;
if strw == width then str else filler + fixedWidthString reqWidth filler str;
# Format a number adding leading zeroes up to fixed width
fixedWidthNumber = width: n: fixedWidthString width "0" (toString n);
} }

View File

@ -24,7 +24,7 @@ rec {
isCpuType = x: isType "cpu-type" x isCpuType = x: isType "cpu-type" x
&& elem x.bits [8 16 32 64 128] && elem x.bits [8 16 32 64 128]
&& (builtins.lessThan 8 x.bits -> isSignificantByte x.significantByte); && (8 < x.bits -> isSignificantByte x.significantByte);
cpuTypes = with significantBytes; cpuTypes = with significantBytes;
setTypes "cpu-type" { setTypes "cpu-type" {

119
lib/tests/modules.sh Executable file
View File

@ -0,0 +1,119 @@
#!/bin/sh
#
# This script is used to test that the module system is working as expected.
# By default it test the version of nixpkgs which is defined in the NIX_PATH.
cd ./modules
pass=0
fail=0
evalConfig() {
local attr=$1
shift;
local script="import ./default.nix { modules = [ $@ ];}"
nix-instantiate --timeout 1 -E "$script" -A "$attr" --eval-only
}
reportFailure() {
local attr=$1
shift;
local script="import ./default.nix { modules = [ $@ ];}"
echo 2>&1 "$ nix-instantiate -E '$script' -A '$attr' --eval-only"
evalConfig "$attr" "$@"
fail=$((fail + 1))
}
checkConfigOutput() {
local outputContains=$1
shift;
if evalConfig "$@" 2>/dev/null | grep --silent "$outputContains" ; then
pass=$((pass + 1))
return 0;
else
echo 2>&1 "error: Expected result matching '$outputContains', while evaluating"
reportFailure "$@"
return 1
fi
}
checkConfigError() {
local errorContains=$1
local err=""
shift;
if err==$(evalConfig "$@" 2>&1 >/dev/null); then
echo 2>&1 "error: Expected error code, got exit code 0, while evaluating"
reportFailure "$@"
return 1
else
if echo "$err" | grep --silent "$errorContains" ; then
pass=$((pass + 1))
return 0;
else
echo 2>&1 "error: Expected error matching '$errorContains', while evaluating"
reportFailure "$@"
return 1
fi
fi
}
# Check boolean option.
checkConfigOutput "false" config.enable ./declare-enable.nix
checkConfigError 'The option .* defined in .* does not exist.' config.enable ./define-enable.nix
# Check mkForce without submodules.
set -- config.enable ./declare-enable.nix ./define-enable.nix
checkConfigOutput "true" "$@"
checkConfigOutput "false" "$@" ./define-force-enable.nix
checkConfigOutput "false" "$@" ./define-enable-force.nix
# Check mkForce with option and submodules.
checkConfigError 'attribute .*foo.* .* not found' config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix
checkConfigOutput 'false' config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix
set -- config.loaOfSub.foo.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo-enable.nix
checkConfigOutput 'true' "$@"
checkConfigOutput 'false' "$@" ./define-force-loaOfSub-foo-enable.nix
checkConfigOutput 'false' "$@" ./define-loaOfSub-force-foo-enable.nix
checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-force-enable.nix
checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-enable-force.nix
# Check overriding effect of mkForce on submodule definitions.
checkConfigError 'attribute .*bar.* .* not found' config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix
checkConfigOutput 'false' config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix ./define-loaOfSub-bar.nix
set -- config.loaOfSub.bar.enable ./declare-loaOfSub-any-enable.nix ./define-loaOfSub-foo.nix ./define-loaOfSub-bar-enable.nix
checkConfigOutput 'true' "$@"
checkConfigError 'attribute .*bar.* .* not found' "$@" ./define-force-loaOfSub-foo-enable.nix
checkConfigError 'attribute .*bar.* .* not found' "$@" ./define-loaOfSub-force-foo-enable.nix
checkConfigOutput 'true' "$@" ./define-loaOfSub-foo-force-enable.nix
checkConfigOutput 'true' "$@" ./define-loaOfSub-foo-enable-force.nix
# Check mkIf with submodules.
checkConfigError 'attribute .*foo.* .* not found' config.loaOfSub.foo.enable ./declare-enable.nix ./declare-loaOfSub-any-enable.nix
set -- config.loaOfSub.foo.enable ./declare-enable.nix ./declare-loaOfSub-any-enable.nix
checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-if-loaOfSub-foo-enable.nix
checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-loaOfSub-if-foo-enable.nix
checkConfigError 'attribute .*foo.* .* not found' "$@" ./define-loaOfSub-foo-if-enable.nix
checkConfigOutput 'false' "$@" ./define-loaOfSub-foo-enable-if.nix
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-if-loaOfSub-foo-enable.nix
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-if-foo-enable.nix
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-foo-if-enable.nix
checkConfigOutput 'true' "$@" ./define-enable.nix ./define-loaOfSub-foo-enable-if.nix
# Check _module.args.
checkConfigOutput "true" config.enable ./declare-enable.nix ./custom-arg-define-enable.nix
# Check _module.check.
set -- config.enable ./declare-enable.nix ./define-enable.nix ./define-loaOfSub-foo.nix
checkConfigError 'The option .* defined in .* does not exist.' "$@"
checkConfigOutput "true" "$@" ./define-module-check.nix
cat <<EOF
====== module tests ======
$pass Pass
$fail Fail
EOF
if test $fail -ne 0; then
exit 1
fi
exit 0

View File

@ -0,0 +1,8 @@
{ lib, custom, ... }:
{
config = {
_module.args.custom = true;
enable = custom;
};
}

View File

@ -0,0 +1,14 @@
{ lib, ... }:
{
options = {
enable = lib.mkOption {
default = false;
example = true;
type = lib.types.bool;
description = ''
Some descriptive text
'';
};
};
}

View File

@ -0,0 +1,29 @@
{ lib, ... }:
let
submod = { ... }: {
options = {
enable = lib.mkOption {
default = false;
example = true;
type = lib.types.bool;
description = ''
Some descriptive text
'';
};
};
};
in
{
options = {
loaOfSub = lib.mkOption {
default = {};
example = {};
type = lib.types.loaOf (lib.types.submodule [ submod ]);
description = ''
Some descriptive text
'';
};
};
}

View File

@ -0,0 +1,7 @@
{ lib ? import <nixpkgs/lib>, modules ? [] }:
{
inherit (lib.evalModules {
inherit modules;
}) config options;
}

View File

@ -0,0 +1,5 @@
{ lib, ... }:
{
enable = lib.mkForce false;
}

View File

@ -0,0 +1,3 @@
{
enable = true;
}

View File

@ -0,0 +1,5 @@
{ lib, ... }:
lib.mkForce {
enable = false;
}

View File

@ -0,0 +1,5 @@
{ lib, ... }:
lib.mkForce {
loaOfSub.foo.enable = false;
}

View File

@ -0,0 +1,5 @@
{ config, lib, ... }:
lib.mkIf config.enable {
loaOfSub.foo.enable = true;
}

View File

@ -0,0 +1,3 @@
{
loaOfSub.bar.enable = true;
}

View File

@ -0,0 +1,3 @@
{
loaOfSub.bar = {};
}

View File

@ -0,0 +1,5 @@
{ lib, ... }:
{
loaOfSub.foo.enable = lib.mkForce false;
}

View File

@ -0,0 +1,5 @@
{ config, lib, ... }:
{
loaOfSub.foo.enable = lib.mkIf config.enable true;
}

View File

@ -0,0 +1,3 @@
{
loaOfSub.foo.enable = true;
}

View File

@ -0,0 +1,7 @@
{ lib, ... }:
{
loaOfSub.foo = lib.mkForce {
enable = false;
};
}

View File

@ -0,0 +1,7 @@
{ config, lib, ... }:
{
loaOfSub.foo = lib.mkIf config.enable {
enable = true;
};
}

View File

@ -0,0 +1,3 @@
{
loaOfSub.foo = {};
}

View File

@ -0,0 +1,7 @@
{ lib, ... }:
{
loaOfSub = lib.mkForce {
foo.enable = false;
};
}

View File

@ -0,0 +1,7 @@
{ config, lib, ... }:
{
loaOfSub = lib.mkIf config.enable {
foo.enable = true;
};
}

View File

@ -0,0 +1,3 @@
{
_module.check = false;
}

31
lib/tests/release.nix Normal file
View File

@ -0,0 +1,31 @@
{ nixpkgs }:
with import ./../.. { };
with lib;
stdenv.mkDerivation {
name = "nixpkgs-lib-tests";
buildInputs = [ nix ];
NIX_PATH="nixpkgs=${nixpkgs}";
buildCommand = ''
datadir="${nix}/share"
export TEST_ROOT=$(pwd)/test-tmp
export NIX_STORE_DIR=$TEST_ROOT/store
export NIX_LOCALSTATE_DIR=$TEST_ROOT/var
export NIX_LOG_DIR=$TEST_ROOT/var/log/nix
export NIX_STATE_DIR=$TEST_ROOT/var/nix
export NIX_DB_DIR=$TEST_ROOT/db
export NIX_CONF_DIR=$TEST_ROOT/etc
export NIX_MANIFESTS_DIR=$TEST_ROOT/var/nix/manifests
export NIX_BUILD_HOOK=
export PAGER=cat
cacheDir=$TEST_ROOT/binary-cache
nix-store --init
cd ${nixpkgs}/lib/tests
./modules.sh
touch $out
'';
}

View File

@ -1,8 +1,3 @@
with {
inherit (import ./lists.nix) deepSeqList;
inherit (import ./attrsets.nix) deepSeqAttrs;
};
rec { rec {
# Identity function. # Identity function.
@ -23,23 +18,11 @@ rec {
# Flip the order of the arguments of a binary function. # Flip the order of the arguments of a binary function.
flip = f: a: b: f b a; flip = f: a: b: f b a;
# `seq x y' evaluates x, then returns y. That is, it forces strict
# evaluation of its first argument.
seq = x: y: if x == null then y else y;
# Like `seq', but recurses into lists and attribute sets to force evaluation
# of all list elements/attributes.
deepSeq = x: y:
if builtins.isList x
then deepSeqList x y
else if builtins.isAttrs x
then deepSeqAttrs x y
else seq x y;
# Pull in some builtins not included elsewhere. # Pull in some builtins not included elsewhere.
inherit (builtins) inherit (builtins)
pathExists readFile isBool isFunction pathExists readFile isBool isFunction
isInt add sub lessThan; isInt add sub lessThan
seq deepSeq;
# Return the Nixpkgs version number. # Return the Nixpkgs version number.
nixpkgsVersion = nixpkgsVersion =
@ -47,7 +30,11 @@ rec {
readFile ../.version readFile ../.version
+ (if pathExists suffixFile then readFile suffixFile else "pre-git"); + (if pathExists suffixFile then readFile suffixFile else "pre-git");
# Whether we're being called by nix-shell. This is useful to # Whether we're being called by nix-shell.
inNixShell = builtins.getEnv "IN_NIX_SHELL" == "1"; inNixShell = builtins.getEnv "IN_NIX_SHELL" == "1";
# Return minimum/maximum of two numbers.
min = x: y: if x < y then x else y;
max = x: y: if x > y then x else y;
} }

View File

@ -6,6 +6,7 @@ with import ./attrsets.nix;
with import ./options.nix; with import ./options.nix;
with import ./trivial.nix; with import ./trivial.nix;
with import ./strings.nix; with import ./strings.nix;
with {inherit (import ./modules.nix) mergeDefinitions; };
rec { rec {
@ -33,9 +34,14 @@ rec {
, # Return a flat list of sub-options. Used to generate , # Return a flat list of sub-options. Used to generate
# documentation. # documentation.
getSubOptions ? prefix: {} getSubOptions ? prefix: {}
, # List of modules if any, or null if none.
getSubModules ? null
, # Function for building the same option type with a different list of
# modules.
substSubModules ? m: null
}: }:
{ _type = "option-type"; { _type = "option-type";
inherit name check merge getSubOptions; inherit name check merge getSubOptions getSubModules substSubModules;
}; };
@ -104,23 +110,33 @@ rec {
listOf = elemType: mkOptionType { listOf = elemType: mkOptionType {
name = "list of ${elemType.name}s"; name = "list of ${elemType.name}s";
check = value: isList value && all elemType.check value; check = isList;
merge = loc: defs: merge = loc: defs:
concatLists (imap (n: def: imap (m: def': map (x: x.value) (filter (x: x ? value) (concatLists (imap (n: def: imap (m: def':
elemType.merge (loc ++ ["[${toString n}-${toString m}]"]) (mergeDefinitions
[{ inherit (def) file; value = def'; }]) def.value) defs); (loc ++ ["[definition ${toString n}-entry ${toString m}]"])
elemType
[{ inherit (def) file; value = def'; }]
).optionalValue
) def.value) defs)));
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]); getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["*"]);
getSubModules = elemType.getSubModules;
substSubModules = m: listOf (elemType.substSubModules m);
}; };
attrsOf = elemType: mkOptionType { attrsOf = elemType: mkOptionType {
name = "attribute set of ${elemType.name}s"; name = "attribute set of ${elemType.name}s";
check = x: isAttrs x && all elemType.check (attrValues x); check = isAttrs;
merge = loc: defs: merge = loc: defs:
zipAttrsWith (name: elemType.merge (loc ++ [name])) mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
(mergeDefinitions (loc ++ [name]) elemType defs).optionalValue
)
# Push down position info. # Push down position info.
(map (def: listToAttrs (mapAttrsToList (n: def': (map (def: listToAttrs (mapAttrsToList (n: def':
{ name = n; value = { inherit (def) file; value = def'; }; }) def.value)) defs); { name = n; value = { inherit (def) file; value = def'; }; }) def.value)) defs)));
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]); getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
getSubModules = elemType.getSubModules;
substSubModules = m: attrsOf (elemType.substSubModules m);
}; };
# List or attribute set of ... # List or attribute set of ...
@ -141,18 +157,19 @@ rec {
attrOnly = attrsOf elemType; attrOnly = attrsOf elemType;
in mkOptionType { in mkOptionType {
name = "list or attribute set of ${elemType.name}s"; name = "list or attribute set of ${elemType.name}s";
check = x: check = x: isList x || isAttrs x;
if isList x then listOnly.check x
else if isAttrs x then attrOnly.check x
else false;
merge = loc: defs: attrOnly.merge loc (imap convertIfList defs); merge = loc: defs: attrOnly.merge loc (imap convertIfList defs);
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]); getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name?>"]);
getSubModules = elemType.getSubModules;
substSubModules = m: loaOf (elemType.substSubModules m);
}; };
uniq = elemType: mkOptionType { uniq = elemType: mkOptionType {
inherit (elemType) name check; inherit (elemType) name check;
merge = mergeOneOption; merge = mergeOneOption;
getSubOptions = elemType.getSubOptions; getSubOptions = elemType.getSubOptions;
getSubModules = elemType.getSubModules;
substSubModules = m: uniq (elemType.substSubModules m);
}; };
nullOr = elemType: mkOptionType { nullOr = elemType: mkOptionType {
@ -165,14 +182,8 @@ rec {
throw "The option `${showOption loc}' is defined both null and not null, in ${showFiles (getFiles defs)}." throw "The option `${showOption loc}' is defined both null and not null, in ${showFiles (getFiles defs)}."
else elemType.merge loc defs; else elemType.merge loc defs;
getSubOptions = elemType.getSubOptions; getSubOptions = elemType.getSubOptions;
}; getSubModules = elemType.getSubModules;
substSubModules = m: nullOr (elemType.substSubModules m);
functionTo = elemType: mkOptionType {
name = "function that evaluates to a(n) ${elemType.name}";
check = isFunction;
merge = loc: defs:
fnArgs: elemType.merge loc (map (fn: { inherit (fn) file; value = fn.value fnArgs; }) defs);
getSubOptions = elemType.getSubOptions;
}; };
submodule = opts: submodule = opts:
@ -187,11 +198,17 @@ rec {
let let
coerce = def: if isFunction def then def else { config = def; }; coerce = def: if isFunction def then def else { config = def; };
modules = opts' ++ map (def: { _file = def.file; imports = [(coerce def.value)]; }) defs; modules = opts' ++ map (def: { _file = def.file; imports = [(coerce def.value)]; }) defs;
in (evalModules { inherit modules; args.name = last loc; prefix = loc; }).config; in (evalModules {
inherit modules;
args.name = last loc;
prefix = loc;
}).config;
getSubOptions = prefix: (evalModules getSubOptions = prefix: (evalModules
{ modules = opts'; inherit prefix; { modules = opts'; inherit prefix;
# FIXME: hack to get shit to evaluate. # FIXME: hack to get shit to evaluate.
args = { name = ""; }; }).options; args = { name = ""; }; }).options;
getSubModules = opts';
substSubModules = m: submodule m;
}; };
enum = values: mkOptionType { enum = values: mkOptionType {

View File

@ -0,0 +1,14 @@
*~
,*
.*.swp
.*.swo
result
result-*
/doc/NEWS.html
/doc/NEWS.txt
/doc/manual.html
/doc/manual.pdf
.version-suffix
.DS_Store
.git

View File

@ -0,0 +1,12 @@
FROM busybox
RUN dir=`mktemp -d` && trap 'rm -rf "$dir"' EXIT && \
wget -O- https://nixos.org/releases/nix/nix-1.7/nix-1.7-x86_64-linux.tar.bz2 | bzcat | tar x -C $dir && \
mkdir -m 0755 /nix && USER=root sh $dir/*/install && \
echo ". /root/.nix-profile/etc/profile.d/nix.sh" >> /etc/profile
ADD . /root/nix/nixpkgs
ONBUILD ENV NIX_PATH nixpkgs=/root/nix/nixpkgs:nixos=/root/nix/nixpkgs/nixos
ONBUILD ENV PATH /root/.nix-profile/bin:/root/.nix-profile/sbin:/bin:/sbin:/usr/bin:/usr/sbin
ONBUILD ENV ENV /etc/profile
ENV ENV /etc/profile

View File

@ -3,7 +3,7 @@
stdenv.mkDerivation { stdenv.mkDerivation {
name = "nix-generate-from-cpan-1"; name = "nix-generate-from-cpan-1";
buildInputs = [ makeWrapper perl perlPackages.YAMLLibYAML perlPackages.JSON ]; buildInputs = [ makeWrapper perl perlPackages.YAMLLibYAML perlPackages.JSON perlPackages.CPANPLUS ];
unpackPhase = "true"; unpackPhase = "true";
buildPhase = "true"; buildPhase = "true";
@ -19,4 +19,4 @@ stdenv.mkDerivation {
maintainers = [ stdenv.lib.maintainers.eelco ]; maintainers = [ stdenv.lib.maintainers.eelco ];
description = "Utility to generate a Nix expression for a Perl package from CPAN"; description = "Utility to generate a Nix expression for a Perl package from CPAN";
}; };
} }

View File

@ -100,7 +100,7 @@ sub get_deps {
foreach my $n (keys %{$deps}) { foreach my $n (keys %{$deps}) {
next if $n eq "perl"; next if $n eq "perl";
# Hacky way to figure out if this module is part of Perl. # Hacky way to figure out if this module is part of Perl.
if ($n !~ /^JSON/ && $n !~ /^YAML/) { if ($n !~ /^JSON/ && $n !~ /^YAML/ && $n !~ /^Module::Pluggable/) {
eval "use $n;"; eval "use $n;";
if (!$@) { if (!$@) {
print STDERR "skipping Perl-builtin module $n\n"; print STDERR "skipping Perl-builtin module $n\n";

View File

@ -62,7 +62,7 @@ for bin in $(find $binaryDist -executable -type f) :; do
) )
if test "$names" = "glibc"; then names="stdenv.glibc"; fi if test "$names" = "glibc"; then names="stdenv.glibc"; fi
if echo $names | grep -c "gcc" &> /dev/null; then names="stdenv.gcc.gcc"; fi if echo $names | grep -c "gcc" &> /dev/null; then names="stdenv.cc.cc"; fi
if test $lib != $libPath; then if test $lib != $libPath; then
interpreter="--interpreter \${$names}/lib/$lib" interpreter="--interpreter \${$names}/lib/$lib"

View File

@ -0,0 +1,41 @@
#! /usr/bin/env bash
set -e
export NIX_CURL_FLAGS=-sS
if [[ $1 == nix ]]; then
echo "=== Installing Nix..."
# Install Nix
bash <(curl -sS https://nixos.org/nix/install)
source $HOME/.nix-profile/etc/profile.d/nix.sh
# Make sure we can use hydra's binary cache
sudo mkdir /etc/nix
sudo tee /etc/nix/nix.conf <<EOF >/dev/null
binary-caches = http://cache.nixos.org http://hydra.nixos.org
trusted-binary-caches = http://hydra.nixos.org
build-max-jobs = 4
EOF
# Verify evaluation
echo "=== Verifying that nixpkgs evaluates..."
nix-env -f. -qa --json >/dev/null
elif [[ $1 == nox ]]; then
echo "=== Installing nox..."
git clone -q https://github.com/madjar/nox
pip --quiet install -e nox
elif [[ $1 == build ]]; then
source $HOME/.nix-profile/etc/profile.d/nix.sh
if [[ $TRAVIS_PULL_REQUEST == false ]]; then
echo "=== Not a pull request"
else
echo "=== Checking PR"
nox-review pr ${TRAVIS_PULL_REQUEST}
fi
# echo "=== Checking tarball creation"
# nix-build pkgs/top-level/release.nix -A tarball
else
echo "$0: Unknown option $1" >&2
false
fi

View File

@ -0,0 +1,112 @@
#!/bin/sh
set -e
: ${NIXOS_CHANNELS:=https://nixos.org/channels/}
: ${CHANNELS_NAMESPACE:=refs/heads/channels/}
# List all channels which are currently in the repository which we would
# have to remove if they are not found again.
deadChannels=$(git for-each-ref --format="%(refname)" "$CHANNELS_NAMESPACE")
updateRef() {
local channelName=$1
local newRev=$2
# if the inputs are not valid, then we do not update any branch.
test -z "$newRev" -o -z "$channelName" && return;
# Update the local refs/heads/channels/* branches to be in-sync with the
# channel references.
local branch=$CHANNELS_NAMESPACE$channelName
oldRev=$(git rev-parse --short "$branch" 2>/dev/null || true)
if test "$oldRev" != "$newRev"; then
if git update-ref "$branch" "$newRev" 2>/dev/null; then
if test -z "$oldRev"; then
echo " * [new branch] $newRev -> ${branch#refs/heads/}"
else
echo " $oldRev..$newRev -> ${branch#refs/heads/}"
fi
else
if test -z "$oldRev"; then
echo " * [missing rev] $newRev -> ${branch#refs/heads/}"
else
echo " [missing rev] $oldRev..$newRev -> ${branch#refs/heads/}"
fi
fi
fi
# Filter out the current channel from the list of dead channels.
deadChannels=$(grep -v "$CHANNELS_NAMESPACE$channelName" <<EOF
$deadChannels
EOF
) ||true
}
# Find the name of all channels which are listed in the directory.
echo "Fetching channels from $NIXOS_CHANNELS:"
for channelName in : $(curl -s "$NIXOS_CHANNELS" | sed -n '/folder/ { s,.*href=",,; s,/".*,,; p }'); do
test "$channelName" = : && continue;
# Do not follow redirections, such that we can extract the
# short-changeset from the name of the directory where we are
# redirected to.
sha1=$(curl -sI "$NIXOS_CHANNELS$channelName" | sed -n '/Location/ { s,.*\.\([a-f0-9]*\)[ \r]*$,\1,; p; }')
updateRef "remotes/$channelName" "$sha1"
done
echo "Fetching channels from nixos-version:"
if currentSystem=$(nixos-version 2>/dev/null); then
# If the system is entirely build from a custom nixpkgs version,
# then the version is not annotated in git version. This sed
# expression is basically matching that the expressions end with
# ".<sha1> (Name)" to extract the sha1.
sha1=$(echo "$currentSystem" | sed -n 's,^.*\.\([a-f0-9]*\) *(.*)$,\1,; T skip; p; :skip;')
updateRef current-system "$sha1"
fi
echo "Fetching channels from $HOME/.nix-defexpr:"
for revFile in : $(find -L "$HOME/.nix-defexpr/" -maxdepth 4 -name svn-revision); do
test "$revFile" = : && continue;
# Deconstruct a path such as, into:
#
# /home/luke/.nix-defexpr/channels_root/nixos/nixpkgs/svn-revision
# channelName = root/nixos
#
# /home/luke/.nix-defexpr/channels/nixpkgs/svn-revision
# channelName = nixpkgs
#
user=${revFile#*.nix-defexpr/channels}
repo=${user#*/}
repo=${repo%%/*}
user=${user%%/*}
user=${user#_}
test -z "$user" && user=$USER
channelName="$user${user:+/}$repo"
sha1=$(sed -n 's,^.*\.\([a-f0-9]*\)$,\1,; T skip; p; :skip;' "$revFile")
updateRef "$channelName" "$sha1"
done
# Suggest to remove channel branches which are no longer found by this
# script. This is to handle the cases where a local/remote channel
# disappear. We should not attempt to remove manually any branches, as they
# might be user branches.
if test -n "$deadChannels"; then
echo "
Some old channel branches are still in your repository, if you
want to remove them, run the following command(s):
"
while read branch; do
echo " git update-ref -d $branch"
done <<EOF
$deadChannels
EOF
echo
fi

View File

@ -0,0 +1,7 @@
viric viriketo@gmail.com
Pjotr Prins pjotr.public01@thebird.nl
Pjotr Prins pjotr.public05@thebird.nl
Wouter den Breejen wbreejen
MarcWeber marcweber
Ricardo Correia Ricardo M. Correia
ertesx@gmx.de ertes

122
maintainers/scripts/vanity.sh Executable file
View File

@ -0,0 +1,122 @@
#! /bin/sh
export LANG=C LC_ALL=C LC_COLLATE=C
# Load git log
raw_git_log="$(git log)"
git_data="$(echo "$raw_git_log" | grep 'Author:' |
sed -e 's/^ *Author://; s/\\//g; s/^ *//; s/ *$//;
s/ @ .*//; s/ *[<]/\t/; s/[>]//')"
# Name - nick - email correspondence from log and from maintainer list
# Also there are a few manual entries
maintainers="$(cat "$(dirname "$0")/../../lib/maintainers.nix" |
grep '=' | sed -re 's/\\"/''/g;
s/ *([^ =]*) *= *" *(.*[^ ]) *[<](.*)[>] *".*/\1\t\2\t\3/')"
git_lines="$( ( echo "$git_data";
cat "$(dirname "$0")/vanity-manual-equalities.txt") | sort |uniq)"
emails="$(
( echo "$maintainers" | cut -f 3; echo "$git_data" | cut -f 2 ) |
sort | uniq | grep -E ".+@.+[.].+"
)"
fetchGithubName () {
commitid="$(
echo "$raw_git_log" | grep -B3 "Author: .*[<]$1[>]" | head -n 3 |
grep '^commit ' | tail -n 1 | sed -e 's/^commit //'
)"
userid="$(
curl https://github.com/NixOS/nixpkgs/commit/"$commitid" 2>/dev/null |
grep authored -B10 | grep 'href="/' |
sed -re 's@.* href="/@@; s@".*@@' |
grep -v "/commit/"
)";
echo "$userid"
}
[ -n "$NIXPKGS_GITHUB_NAME_CACHE" ] && {
echo "$emails" | while read email; do
line="$(grep "$email " "$NIXPKGS_GITHUB_NAME_CACHE")"
[ -z "$line" ] && {
echo "$email $(fetchGithubName "$email")" >> \
"$NIXPKGS_GITHUB_NAME_CACHE"
}
done
}
# For RDF
normalize_name () {
sed -e 's/%/%25/g; s/ /%20/g; s/'\''/%27/g; s/"/%22/g; s/`/%60/g; s/\^/%5e/g; '
}
denormalize_name () {
sed -e 's/%20/ /g; s/%27/'\''/g; s/%22/"/g; s/%60/`/g; s/%5e/^/g; s/%25/%/g;';
}
n3="$(mktemp --suffix .n3)"
# «The same person» relation and a sorting hint
# Full name is something with a space
(
echo "$git_lines" | sed -re 's@(.*)\t(.*)@<my://name/\1> <my://can-be> <my://name/\2>.@'
echo "$git_lines" | sed -re 's@(.*)\t(.*)@<my://name/\2> <my://can-be> <my://name/\1>.@'
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\1> <my://can-be> <my://name/\2>.@'
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\2> <my://can-be> <my://name/\3>.@'
echo "$maintainers" | sed -re 's@(.*)\t(.*)\t(.*)@<my://name/\3> <my://can-be> <my://name/\1>.@'
echo "$git_lines" | grep ' ' | cut -f 1 | sed -e 's@.*@<my://name/&> <my://is-name> <my://0>.@'
echo "$git_lines" | grep -v ' ' | cut -f 1 | sed -e 's@.*@<my://name/&> <my://is-name> <my://1>.@'
echo "$maintainers" | cut -f 2 | sed -e 's@.*@<my://name/&> <my://is-name> <my://0>.@'
[ -n "$NIXPKGS_GITHUB_NAME_CACHE" ] && cat "$NIXPKGS_GITHUB_NAME_CACHE" |
grep -v " $" |
sed -re 's@(.*)\t(.*)@<my://name/\1> <my://at-github> <my://github/\2>.@'
) | normalize_name | grep -E '<my://[-a-z]+>' | sort | uniq > "$n3"
# Get transitive closure
sparql="$(nix-build '<nixpkgs>' -Q -A apache-jena --no-out-link)/bin/sparql"
name_list="$(
"$sparql" --results=TSV --data="$n3" "
select ?x ?y ?g where {
?x <my://can-be>+ ?y.
?x <my://is-name> ?g.
}
" | tail -n +2 |
sed -re 's@<my://name/@@g; s@<my://@@g; s@>@@g;' |
sort -k 2,3 -t ' '
)"
github_name_list="$(
"$sparql" --results=TSV --data="$n3" "
select ?x ?y where {
?x (<my://can-be>+ / <my://at-github>) ?y.
}
" | tail -n +2 |
sed -re 's@<my://(name|github)/@@g; s@<my://@@g; s@>@@g;'
)"
# Take first spelling option for every person
name_list_canonical="$(echo "$name_list" | cut -f 1,2 | uniq -f1)"
cleaner_script="$(echo "$name_list_canonical" | denormalize_name |
sed -re 's/(.*)\t(.*)/s#^\2$#\1#g/g')"
# Add github usernames
if [ -n "$NIXPKGS_GITHUB_NAME_CACHE" ]; then
github_adder_script="$(echo "$github_name_list" |
grep -E "$(echo "$name_list_canonical" | cut -f 2 |
tr '\n' '|' )" |
sort | uniq |
sed -re 's/(.*)\t(.*)/s| \1$| \1\t\2|g;/' |
denormalize_name
)"
else
github_adder_script=''
fi
echo "$name_list" | denormalize_name
echo
echo "$git_data" | cut -f 1 |
sed -e "$cleaner_script" |
sort | uniq -c | sort -k1n | sed -re "$github_adder_script" |
sed -re 's/^ *([0-9]+) /\1\t/'

View File

@ -58,12 +58,10 @@ controls memory allocation limits; by default, all processes are in
the top-level cgroup, so any service or session can exhaust all the top-level cgroup, so any service or session can exhaust all
available memory. Per-cgroup memory limits can be specified in available memory. Per-cgroup memory limits can be specified in
<filename>configuration.nix</filename>; for instance, to limit <filename>configuration.nix</filename>; for instance, to limit
<literal>httpd.service</literal> to 512 MiB of RAM (excluding swap) <literal>httpd.service</literal> to 512 MiB of RAM (excluding swap):
and 640 MiB of RAM (including swap):
<programlisting> <programlisting>
systemd.services.httpd.serviceConfig.MemoryLimit = "512M"; systemd.services.httpd.serviceConfig.MemoryLimit = "512M";
systemd.services.httpd.serviceConfig.ControlGroupAttribute = [ "memory.memsw.limit_in_bytes 640M" ];
</programlisting> </programlisting>
</para> </para>
@ -72,4 +70,4 @@ systemd.services.httpd.serviceConfig.ControlGroupAttribute = [ "memory.memsw.lim
continuously updated list of all cgroups with their CPU and memory continuously updated list of all cgroups with their CPU and memory
usage.</para> usage.</para>
</chapter> </chapter>

View File

@ -49,4 +49,8 @@ on container networking.)</para>
switch</literal>. Note that this will not delete the root directory of switch</literal>. Note that this will not delete the root directory of
the container in <literal>/var/lib/containers</literal>.</para> the container in <literal>/var/lib/containers</literal>.</para>
</section> <para>Declarative containers can be started and stopped using the
corresponding systemd service, e.g. <literal>systemctl start
container@database</literal>.</para>
</section>

View File

@ -12,9 +12,9 @@ pre-built binary. That is, whenever a command like
<command>nixos-rebuild</command> needs a path in the Nix store, Nix <command>nixos-rebuild</command> needs a path in the Nix store, Nix
will try to download that path from the Internet rather than build it will try to download that path from the Internet rather than build it
from source. The default binary cache is from source. The default binary cache is
<uri>http://cache.nixos.org/</uri>. If this cache is unreachable, Nix <uri>https://cache.nixos.org/</uri>. If this cache is unreachable,
operations may take a long time due to HTTP connection timeouts. You Nix operations may take a long time due to HTTP connection timeouts.
can disable the use of the binary cache by adding <option>--option You can disable the use of the binary cache by adding <option>--option
use-binary-caches false</option>, e.g. use-binary-caches false</option>, e.g.
<screen> <screen>
@ -30,4 +30,4 @@ $ nixos-rebuild switch --option binary-caches http://my-cache.example.org/
</para> </para>
</section> </section>

View File

@ -68,7 +68,7 @@ instance, if you try to define an option that doesnt exist (that is,
doesnt have a corresponding <emphasis>option declaration</emphasis>), doesnt have a corresponding <emphasis>option declaration</emphasis>),
<command>nixos-rebuild</command> will give an error like: <command>nixos-rebuild</command> will give an error like:
<screen> <screen>
The option `services.httpd.enabl' defined in `/etc/nixos/configuration.nix' does not exist. The option `services.httpd.enable' defined in `/etc/nixos/configuration.nix' does not exist.
</screen> </screen>
Likewise, values in option definitions must have a correct type. For Likewise, values in option definitions must have a correct type. For
instance, <option>services.httpd.enable</option> must be a Boolean instance, <option>services.httpd.enable</option> must be a Boolean

View File

@ -12,12 +12,9 @@ interfaces. However, you can configure an interface manually as
follows: follows:
<programlisting> <programlisting>
networking.interfaces.eth0 = { ipAddress = "192.168.1.2"; prefixLength = 24; }; networking.interfaces.eth0.ip4 = [ { address = "192.168.1.2"; prefixLength = 24; } ];
</programlisting> </programlisting>
(The network prefix can also be specified using the option
<literal>subnetMask</literal>,
e.g. <literal>"255.255.255.0"</literal>, but this is deprecated.)
Typically youll also want to set a default gateway and set of name Typically youll also want to set a default gateway and set of name
servers: servers:

View File

@ -56,7 +56,7 @@ root file system), you can use
boot.initrd.extraKernelModules = [ "cifs" ]; boot.initrd.extraKernelModules = [ "cifs" ];
</programlisting> </programlisting>
This causes the specified modules and their dependencies to be added This causes the specified modules and their dependencies to be added
to the initial ramdark.</para> to the initial ramdisk.</para>
<para>Kernel runtime parameters can be set through <para>Kernel runtime parameters can be set through
<option>boot.kernel.sysctl</option>, e.g. <option>boot.kernel.sysctl</option>, e.g.

View File

@ -10,17 +10,17 @@
use NetworkManager. You can enable NetworkManager by setting: use NetworkManager. You can enable NetworkManager by setting:
<programlisting> <programlisting>
services.networkmanager.enable = true; networking.networkmanager.enable = true;
</programlisting> </programlisting>
Some desktop managers (e.g., GNOME) enable NetworkManager some desktop managers (e.g., GNOME) enable NetworkManager
automatically for you.</para> automatically for you.</para>
<para>All users that should have permission to change network settings <para>All users that should have permission to change network settings
must belong to the <code>networkmanager</code> group.</para> must belong to the <code>networkmanager</code> group.</para>
<note><para><code>services.networkmanager</code> and <note><para><code>networking.networkmanager</code> and
<code>services.wireless</code> can not be enabled at the same time: <code>networking.wireless</code> can not be enabled at the same time:
you can still connect to the wireless networks using you can still connect to the wireless networks using
NetworkManager.</para></note> NetworkManager.</para></note>

View File

@ -60,7 +60,7 @@ manual</link> for the rest.</para>
<entry>A nested set, equivalent to <literal>{ foo = { bar = 1; }; }</literal></entry> <entry>A nested set, equivalent to <literal>{ foo = { bar = 1; }; }</literal></entry>
</row> </row>
<row> <row>
<entry><literal>rec { x = "bla"; y = x + "bar"; }</literal></entry> <entry><literal>rec { x = "foo"; y = x + "bar"; }</literal></entry>
<entry>A recursive set, equivalent to <literal>{ x = "foo"; y = "foobar"; }</literal></entry> <entry>A recursive set, equivalent to <literal>{ x = "foo"; y = "foobar"; }</literal></entry>
</row> </row>
<row> <row>

View File

@ -67,12 +67,31 @@ with other kernel modules.</para>
<para>On 64-bit systems, if you want full acceleration for 32-bit <para>On 64-bit systems, if you want full acceleration for 32-bit
programs such as Wine, you should also set the following: programs such as Wine, you should also set the following:
<programlisting> <programlisting>
services.xserver.driSupport32Bit = true; hardware.opengl.driSupport32Bit = true;
</programlisting> </programlisting>
</para> </para>
</simplesect> </simplesect>
<simplesect><title>AMD Graphics Cards</title>
<para>AMD provides a proprietary driver for its graphics cards that
has better 3D performance than the X.org drivers. It is not enabled
by default because its not free software. You can enable it as follows:
<programlisting>
services.xserver.videoDrivers = [ "ati_unfree" ];
</programlisting>
You will need to reboot after enabling this driver to prevent a clash
with other kernel modules.</para>
<para>On 64-bit systems, if you want full acceleration for 32-bit
programs such as Wine, you should also set the following:
<programlisting>
hardware.opengl.driSupport32Bit = true;
</programlisting>
</para>
</simplesect>
<simplesect><title>Touchpads</title> <simplesect><title>Touchpads</title>

View File

@ -6,12 +6,22 @@ with pkgs.lib;
let let
# Remove invisible and internal options. # Remove invisible and internal options.
options' = filter (opt: opt.visible && !opt.internal) (optionAttrSetToDocList options); optionsList = filter (opt: opt.visible && !opt.internal) (optionAttrSetToDocList options);
# Replace functions by the string <function>
substFunction = x:
if builtins.isAttrs x then mapAttrs (name: substFunction) x
else if builtins.isList x then map substFunction x
else if builtins.isFunction x then "<function>"
else x;
# Clean up declaration sites to not refer to the NixOS source tree. # Clean up declaration sites to not refer to the NixOS source tree.
options'' = flip map options' (opt: opt // { optionsList' = flip map optionsList (opt: opt // {
declarations = map (fn: stripPrefix fn) opt.declarations; declarations = map (fn: stripPrefix fn) opt.declarations;
}); }
// optionalAttrs (opt ? example) { example = substFunction opt.example; }
// optionalAttrs (opt ? default) { default = substFunction opt.default; }
// optionalAttrs (opt ? type) { type = substFunction opt.type; });
prefix = toString ../../..; prefix = toString ../../..;
@ -21,10 +31,14 @@ let
else else
fn; fn;
optionsXML = builtins.toFile "options.xml" (builtins.unsafeDiscardStringContext (builtins.toXML options'')); # Convert the list of options into an XML file. The builtin
# unsafeDiscardStringContext is used to prevent the realisation of
# the store paths which are used in options definitions.
optionsXML = builtins.toFile "options.xml" (builtins.unsafeDiscardStringContext (builtins.toXML optionsList'));
optionsDocBook = runCommand "options-db.xml" {} '' optionsDocBook = runCommand "options-db.xml" {} ''
if grep /nixpkgs/nixos/modules ${optionsXML}; then optionsXML=${optionsXML}
if grep /nixpkgs/nixos/modules $optionsXML; then
echo "The manual appears to depend on the location of Nixpkgs, which is bad" echo "The manual appears to depend on the location of Nixpkgs, which is bad"
echo "since this prevents sharing via the NixOS channel. This is typically" echo "since this prevents sharing via the NixOS channel. This is typically"
echo "caused by an option default that refers to a relative path (see above" echo "caused by an option default that refers to a relative path (see above"
@ -33,7 +47,7 @@ let
fi fi
${libxslt}/bin/xsltproc \ ${libxslt}/bin/xsltproc \
--stringparam revision '${revision}' \ --stringparam revision '${revision}' \
-o $out ${./options-to-docbook.xsl} ${optionsXML} -o $out ${./options-to-docbook.xsl} $optionsXML
''; '';
sources = sourceFilesBySuffices ./. [".xml"]; sources = sourceFilesBySuffices ./. [".xml"];
@ -49,6 +63,26 @@ let
in rec { in rec {
# The NixOS options in JSON format.
optionsJSON = stdenv.mkDerivation {
name = "options-json";
buildCommand = ''
# Export list of options in different format.
dst=$out/share/doc/nixos
mkdir -p $dst
cp ${builtins.toFile "options.json" (builtins.unsafeDiscardStringContext (builtins.toJSON
(listToAttrs (map (o: { name = o.name; value = removeAttrs o ["name" "visible" "internal"]; }) optionsList'))))
} $dst/options.json
mkdir -p $out/nix-support
echo "file json $dst/options.json" >> $out/nix-support/hydra-build-products
''; # */
meta.description = "List of NixOS options in JSON format";
};
# Generate the NixOS manual. # Generate the NixOS manual.
manual = stdenv.mkDerivation { manual = stdenv.mkDerivation {
name = "nixos-manual"; name = "nixos-manual";
@ -90,7 +124,7 @@ in rec {
mkdir -p $out/nix-support mkdir -p $out/nix-support
echo "nix-build out $out" >> $out/nix-support/hydra-build-products echo "nix-build out $out" >> $out/nix-support/hydra-build-products
echo "doc manual $dst manual.html" >> $out/nix-support/hydra-build-products echo "doc manual $dst" >> $out/nix-support/hydra-build-products
''; # */ ''; # */
meta.description = "The NixOS manual in HTML format"; meta.description = "The NixOS manual in HTML format";

View File

@ -39,24 +39,13 @@ $ firefox result/log.html
</para> </para>
<para>It is also possible to run the test environment interactively, <title>Running Tests interactively</title>
allowing you to experiment with the VMs. For example:
<screen> <para>The test itself can be run interactively. This is
$ nix-build login.nix -A driver
$ ./result/bin/nixos-run-vms
</screen>
The script <command>nixos-run-vms</command> starts the virtual
machines defined by test. The root file system of the VMs is created
on the fly and kept across VM restarts in
<filename>./</filename><varname>hostname</varname><filename>.qcow2</filename>.</para>
<para>Finally, the test itself can be run interactively. This is
particularly useful when developing or debugging a test: particularly useful when developing or debugging a test:
<screen> <screen>
$ nix-build tests/ -A nfs.driver $ nix-build nixos/tests/login.nix -A driver
$ ./result/bin/nixos-test-driver $ ./result/bin/nixos-test-driver
starting VDE switch for network 1 starting VDE switch for network 1
&gt; &gt;
@ -66,6 +55,7 @@ You can then take any Perl statement, e.g.
<screen> <screen>
&gt; startAll &gt; startAll
&gt; testScript
&gt; $machine->succeed("touch /tmp/foo") &gt; $machine->succeed("touch /tmp/foo")
</screen> </screen>
@ -74,4 +64,16 @@ script and drops you back into the test driver command line upon its
completion. This allows you to inspect the state of the VMs after the completion. This allows you to inspect the state of the VMs after the
test (e.g. to debug the test script).</para> test (e.g. to debug the test script).</para>
</section> <para>To just start and experiment with the VMs, run:
<screen>
$ nix-build nixos/tests/login.nix -A driver
$ ./result/bin/nixos-run-vms
</screen>
The script <command>nixos-run-vms</command> starts the virtual
machines defined by test. The root file system of the VMs is created
on the fly and kept across VM restarts in
<filename>./</filename><varname>hostname</varname><filename>.qcow2</filename>.</para>
</section>

View File

@ -40,20 +40,22 @@ rebuild everything from source. So you may want to create a local
branch based on your current NixOS version: branch based on your current NixOS version:
<screen> <screen>
$ nixos-version $ <replaceable>/my/sources</replaceable>/nixpkgs/maintainers/scripts/update-channel-branches.sh
14.04.273.ea1952b (Baboon) Fetching channels from https://nixos.org/channels:
* [new branch] cbe467e -> channels/remotes/nixos-unstable
$ git checkout -b local ea1952b Fetching channels from nixos-version:
* [new branch] 9ff4738 -> channels/current-system
Fetching channels from ~/.nix-defexpr:
* [new branch] 0d4acad -> channels/root/nixos
$ git checkout -b local channels/current-system
</screen> </screen>
Or, to base your local branch on the latest version available in the Or, to base your local branch on the latest version available in the
NixOS channel: NixOS channel:
<screen> <screen>
$ curl -sI http://nixos.org/channels/nixos-unstable/ | grep Location $ <replaceable>/my/sources</replaceable>/nixpkgs/maintainers/scripts/update-channel-branches.sh
Location: http://releases.nixos.org/nixos/unstable/nixos-14.10pre43986.acaf4a6/ $ git checkout -b local channels/remotes/nixos-unstable
$ git checkout -b local acaf4a6
</screen> </screen>
You can then use <command>git rebase</command> to sync your local You can then use <command>git rebase</command> to sync your local
@ -92,4 +94,4 @@ to <command>nix-env</command>, as it will break after interpreting expressions
in <filename>nixos/</filename> as packages.</para> in <filename>nixos/</filename> as packages.</para>
--> -->
</chapter> </chapter>

View File

@ -11,14 +11,9 @@
<listitem><para>Boot from the CD.</para></listitem> <listitem><para>Boot from the CD.</para></listitem>
<listitem><para>The CD contains a basic NixOS installation. (It <listitem><para>The CD contains a basic NixOS installation. (It
also contains Memtest86+, useful if you want to test new hardware.) also contains Memtest86+, useful if you want to test new hardware).
When its finished booting, it should have detected most of your When its finished booting, it should have detected most of your
hardware and brought up networking (check hardware.</para></listitem>
<command>ifconfig</command>). Networking is necessary for the
installer, since it will download lots of stuff (such as source
tarballs or Nixpkgs channel binaries). Its best if you have a DHCP
server on your network. Otherwise configure networking manually
using <command>ifconfig</command>.</para></listitem>
<listitem><para>The NixOS manual is available on virtual console 8 <listitem><para>The NixOS manual is available on virtual console 8
(press Alt+F8 to access).</para></listitem> (press Alt+F8 to access).</para></listitem>
@ -29,6 +24,16 @@
<listitem><para>If you downloaded the graphical ISO image, you can <listitem><para>If you downloaded the graphical ISO image, you can
run <command>start display-manager</command> to start KDE.</para></listitem> run <command>start display-manager</command> to start KDE.</para></listitem>
<listitem><para>The boot process should have brought up networking (check
<command>ip a</command>). Networking is necessary for the
installer, since it will download lots of stuff (such as source
tarballs or Nixpkgs channel binaries). Its best if you have a DHCP
server on your network. Otherwise configure networking manually
using <command>ifconfig</command>.</para>
<para>To manually configure the network on the graphical installer,
first disable network-manager with
<command>systemctl stop network-manager</command>.</para></listitem>
<listitem><para>The NixOS installer doesnt do any partitioning or <listitem><para>The NixOS installer doesnt do any partitioning or
formatting yet, so you need to that yourself. Use the following formatting yet, so you need to that yourself. Use the following
commands: commands:

View File

@ -8,9 +8,14 @@
<para>NixOS ISO images can be downloaded from the <link <para>NixOS ISO images can be downloaded from the <link
xlink:href="http://nixos.org/nixos/download.html">NixOS xlink:href="http://nixos.org/nixos/download.html">NixOS
homepage</link>. These can be burned onto a CD. It is also possible download page</link>. There are a number of installation options. If
to copy them onto a USB stick and install NixOS from there. For you happen to have an optical drive and a spare CD, burning the
details, see the <link image to CD and booting from that is probably the easiest option.
Most people will need to prepare a USB stick to boot from.
Unetbootin is recommended and the process is described in brief below.
Note that systems which use UEFI require some additional manual steps.
If you run into difficulty a number of alternative methods are presented
in the <link
xlink:href="https://nixos.org/wiki/Installing_NixOS_from_a_USB_stick">NixOS xlink:href="https://nixos.org/wiki/Installing_NixOS_from_a_USB_stick">NixOS
Wiki</link>.</para> Wiki</link>.</para>
@ -22,7 +27,7 @@ running NixOS system through several other means:
<para>Using virtual appliances in Open Virtualization Format (OVF) <para>Using virtual appliances in Open Virtualization Format (OVF)
that can be imported into VirtualBox. These are available from that can be imported into VirtualBox. These are available from
the <link xlink:href="http://nixos.org/nixos/download.html">NixOS the <link xlink:href="http://nixos.org/nixos/download.html">NixOS
homepage</link>.</para> download page</link>.</para>
</listitem> </listitem>
<listitem> <listitem>
<para>Using AMIs for Amazons EC2. To find one for your region <para>Using AMIs for Amazons EC2. To find one for your region

View File

@ -14,8 +14,8 @@ been built. These channels are:
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para>Stable channels, such as <literal <para><emphasis>Stable channels</emphasis>, such as <literal
xlink:href="http://nixos.org/channels/nixos-14.04">nixos-14.04</literal>. xlink:href="https://nixos.org/channels/nixos-14.12">nixos-14.12</literal>.
These only get conservative bug fixes and package upgrades. For These only get conservative bug fixes and package upgrades. For
instance, a channel update may cause the Linux kernel on your instance, a channel update may cause the Linux kernel on your
system to be upgraded from 3.4.66 to 3.4.67 (a minor bug fix), but system to be upgraded from 3.4.66 to 3.4.67 (a minor bug fix), but
@ -23,26 +23,40 @@ been built. These channels are:
3.11.<replaceable>x</replaceable> (a major change that has the 3.11.<replaceable>x</replaceable> (a major change that has the
potential to break things). Stable channels are generally potential to break things). Stable channels are generally
maintained until the next stable branch is created.</para> maintained until the next stable branch is created.</para>
<para></para>
</listitem> </listitem>
<listitem> <listitem>
<para>The unstable channel, <literal <para>The <emphasis>unstable channel</emphasis>, <literal
xlink:href="http://nixos.org/channels/nixos-unstable">nixos-unstable</literal>. xlink:href="https://nixos.org/channels/nixos-unstable">nixos-unstable</literal>.
This corresponds to NixOSs main development branch, and may thus This corresponds to NixOSs main development branch, and may thus
see radical changes between channel updates. Its not recommended see radical changes between channel updates. Its not recommended
for production systems.</para> for production systems.</para>
</listitem> </listitem>
<listitem>
<para><emphasis>Small channels</emphasis>, such as <literal
xlink:href="https://nixos.org/channels/nixos-14.12-small">nixos-14.12-small</literal>
or <literal
xlink:href="https://nixos.org/channels/nixos-unstable-small">nixos-unstable-small</literal>. These
are identical to the stable and unstable channels described above,
except that they contain fewer binary packages. This means they
get updated faster than the regular channels (for instance, when a
critical security patch is committed to NixOSs source tree), but
may require more packages to be built from source than
usual. Theyre mostly intended for server environments and as such
contain few GUI applications.</para>
</listitem>
</itemizedlist> </itemizedlist>
To see what channels are available, go to <link To see what channels are available, go to <link
xlink:href="http://nixos.org/channels"/>. (Note that the URIs of the xlink:href="https://nixos.org/channels"/>. (Note that the URIs of the
various channels redirect to a directory that contains the channels various channels redirect to a directory that contains the channels
latest version and includes ISO images and VirtualBox latest version and includes ISO images and VirtualBox
appliances.)</para> appliances.)</para>
<para>When you first install NixOS, youre automatically subscribed to <para>When you first install NixOS, youre automatically subscribed to
the NixOS channel that corresponds to your installation source. For the NixOS channel that corresponds to your installation source. For
instance, if you installed from a 14.04 ISO, you will be subscribed to instance, if you installed from a 14.12 ISO, you will be subscribed to
the <literal>nixos-14.04</literal> channel. To see which NixOS the <literal>nixos-14.12</literal> channel. To see which NixOS
channel youre subscribed to, run the following as root: channel youre subscribed to, run the following as root:
<screen> <screen>
@ -53,20 +67,26 @@ nixos https://nixos.org/channels/nixos-unstable
To switch to a different NixOS channel, do To switch to a different NixOS channel, do
<screen> <screen>
$ nix-channel --add http://nixos.org/channels/<replaceable>channel-name</replaceable> nixos $ nix-channel --add https://nixos.org/channels/<replaceable>channel-name</replaceable> nixos
</screen> </screen>
(Be sure to include the <literal>nixos</literal> parameter at the (Be sure to include the <literal>nixos</literal> parameter at the
end.) For instance, to use the NixOS 14.04 stable channel: end.) For instance, to use the NixOS 14.12 stable channel:
<screen> <screen>
$ nix-channel --add http://nixos.org/channels/nixos-14.04 nixos $ nix-channel --add https://nixos.org/channels/nixos-14.12 nixos
</screen> </screen>
But it you want to live on the bleeding edge: If you have a server, you may want to use the “small” channel instead:
<screen> <screen>
$ nix-channel --add http://nixos.org/channels/nixos-unstable nixos $ nix-channel --add https://nixos.org/channels/nixos-14.12-small nixos
</screen>
And if you want to live on the bleeding edge:
<screen>
$ nix-channel --add https://nixos.org/channels/nixos-unstable nixos
</screen> </screen>
</para> </para>

View File

@ -11,12 +11,45 @@
<refnamediv> <refnamediv>
<refname><command>nixos-install</command></refname> <refname><command>nixos-install</command></refname>
<refpurpose>install NixOS</refpurpose> <refpurpose>install bootloader and NixOS</refpurpose>
</refnamediv> </refnamediv>
<refsynopsisdiv> <refsynopsisdiv>
<cmdsynopsis> <cmdsynopsis>
<command>nixos-install</command> <command>nixos-install</command>
<arg>
<arg choice='plain'><option>-I</option></arg>
<replaceable>path</replaceable>
</arg>
<arg>
<arg choice='plain'><option>--root</option></arg>
<replaceable>root</replaceable>
</arg>
<arg>
<group choice='req'>
<arg choice='plain'><option>--max-jobs</option></arg>
<arg choice='plain'><option>-j</option></arg>
</group>
<replaceable>number</replaceable>
</arg>
<arg>
<option>--cores</option>
<replaceable>number</replaceable>
</arg>
<arg>
<option>--option</option>
<replaceable>name</replaceable>
<replaceable>value</replaceable>
</arg>
<arg>
<arg choice='plain'><option>--show-trace</option></arg>
</arg>
<arg>
<arg choice='plain'><option>--chroot</option></arg>
</arg>
<arg>
<arg choice='plain'><option>--help</option></arg>
</arg>
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -55,6 +88,87 @@ it.</para>
</refsection> </refsection>
<refsection><title>Options</title>
<para>This command accepts the following options:</para>
<variablelist>
<varlistentry>
<term><option>--root</option></term>
<listitem>
<para>Defaults to <filename>/mnt</filename>. If this option is given, treat the directory
<replaceable>root</replaceable> as the root of the NixOS installation.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-I</option></term>
<listitem>
<para>Add a path to the Nix expression search path. This option may be given multiple times.
See the NIX_PATH environment variable for information on the semantics of the Nix search path.
Paths added through <replaceable>-I</replaceable> take precedence over NIX_PATH.</para>
</listitem>
</varlistentry>
<varlistentry><term><option>--max-jobs</option></term>
<term><option>-j</option></term>
<listitem><para>Sets the maximum number of build jobs that Nix will
perform in parallel to the specified number. The default is <literal>1</literal>.
A higher value is useful on SMP systems or to exploit I/O latency.</para></listitem>
</varlistentry>
<varlistentry><term><option>--cores</option></term>
<listitem><para>Sets the value of the <envar>NIX_BUILD_CORES</envar>
environment variable in the invocation of builders. Builders can
use this variable at their discretion to control the maximum amount
of parallelism. For instance, in Nixpkgs, if the derivation
attribute <varname>enableParallelBuilding</varname> is set to
<literal>true</literal>, the builder passes the
<option>-j<replaceable>N</replaceable></option> flag to GNU Make.
The value <literal>0</literal> means that the builder should use all
available CPU cores in the system.</para></listitem>
</varlistentry>
<varlistentry><term><option>--option</option> <replaceable>name</replaceable> <replaceable>value</replaceable></term>
<listitem><para>Set the Nix configuration option
<replaceable>name</replaceable> to <replaceable>value</replaceable>.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--show-trace</option></term>
<listitem>
<para>Causes Nix to print out a stack trace in case of Nix expression evaluation errors.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--chroot</option></term>
<listitem>
<para>Chroot into given installation. Any additional arguments passed are going to be executed inside the chroot.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--help</option></term>
<listitem>
<para>Synonym for <command>man nixos-install</command>.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><title>Examples</title> <refsection><title>Examples</title>
@ -72,6 +186,7 @@ $ mount /dev/sda1 /mnt
$ nixos-generate-config --root /mnt $ nixos-generate-config --root /mnt
$ # edit /mnt/etc/nixos/configuration.nix $ # edit /mnt/etc/nixos/configuration.nix
$ nixos-install $ nixos-install
$ reboot
</screen> </screen>
</para> </para>

View File

@ -17,11 +17,6 @@
<refsynopsisdiv> <refsynopsisdiv>
<cmdsynopsis> <cmdsynopsis>
<command>nixos-option</command> <command>nixos-option</command>
<group choice="opt">
<option>-v</option>
<option>-d</option>
<option>-l</option>
</group>
<arg choice='plain'><replaceable>option.name</replaceable></arg> <arg choice='plain'><replaceable>option.name</replaceable></arg>
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -31,50 +26,13 @@
<para>This command evaluates the configuration specified in <para>This command evaluates the configuration specified in
<filename>/etc/nixos/configuration.nix</filename> and returns the properties <filename>/etc/nixos/configuration.nix</filename> and returns the properties
of the option name given as argument. By default, it returns the value of of the option name given as argument.</para>
the option.</para>
<para>When the option name is not an option, the command prints the list of <para>When the option name is not an option, the command prints the list of
attributes contained in the attribute set.</para> attributes contained in the attribute set.</para>
</refsection> </refsection>
<refsection><title>Options</title>
<para>This command accepts the following options:</para>
<variablelist>
<varlistentry>
<term><option>--value</option>, <option>-v</option></term>
<listitem>
<para>Returns the value of the option. This is the default operation
if no other options are defined.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--description</option>, <option>-d</option></term>
<listitem>
<para>Return the default value, the example and the description of the
option when available.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--lookup</option>, <option>-l</option></term>
<listitem>
<para>Return the locations where the option is declared and where it
is defined. This is extremely useful to find sources of errors in
your configuration.</para>
</listitem>
</varlistentry>
</variablelist>
</refsection>
<refsection><title>Environment</title> <refsection><title>Environment</title>
<variablelist> <variablelist>
@ -103,27 +61,21 @@ grub
initScript initScript
$ nixos-option boot.loader.grub.enable $ nixos-option boot.loader.grub.enable
true</screen></para> Value:
true
<para>Prints option information: Default:
true
<screen>$ nixos-option -d networking.hostName
Default: "nixos"
Description: Description:
The name of the machine. Leave it empty if you want to obtain Whether to enable the GNU GRUB boot loader.
it from a DHCP server (if using DHCP).</screen></para>
<para>Find the locations which are declaring and defining an option:
<screen>$ nixos-option -l hardware.firmware
Declared by: Declared by:
/mnt/data/nix-sources/nixos/modules/services/hardware/udev.nix "/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix"
Defined by: Defined by:
/path/to/nixpkgs/nixos/modules/system/boot/kernel.nix "/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix"
/path/to/nixpkgs/nixos/modules/hardware/network/rt73.nix </screen></para>
/path/to/nixpkgs/nixos/modules/hardware/network/intel-3945abg.nix
/path/to/nixpkgs/nixos/modules/hardware/network/intel-2200bg.nix</screen></para>
</refsection> </refsection>

View File

@ -1,7 +1,7 @@
<refentry xmlns="http://docbook.org/ns/docbook" <refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"> xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta> <refmeta>
<refentrytitle><command>nixos-rebuild</command></refentrytitle> <refentrytitle><command>nixos-rebuild</command></refentrytitle>
<manvolnum>8</manvolnum> <manvolnum>8</manvolnum>
@ -22,7 +22,8 @@
<arg choice='plain'><option>boot</option></arg> <arg choice='plain'><option>boot</option></arg>
<arg choice='plain'><option>test</option></arg> <arg choice='plain'><option>test</option></arg>
<arg choice='plain'><option>build</option></arg> <arg choice='plain'><option>build</option></arg>
<arg choice='plain'><option>dry-run</option></arg> <arg choice='plain'><option>dry-build</option></arg>
<arg choice='plain'><option>dry-activate</option></arg>
<arg choice='plain'><option>build-vm</option></arg> <arg choice='plain'><option>build-vm</option></arg>
<arg choice='plain'><option>build-vm-with-bootloader</option></arg> <arg choice='plain'><option>build-vm-with-bootloader</option></arg>
</group> </group>
@ -114,10 +115,22 @@ $ nix-build /path/to/nixpkgs/nixos -A system
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><option>dry-run</option></term> <term><option>dry-build</option></term>
<listitem> <listitem>
<para>Simply show what store paths would be built or downloaded <para>Show what store paths would be built or downloaded by any
by any of the operations above.</para> of the operations above, but otherwise do nothing.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>dry-activate</option></term>
<listitem>
<para>Build the new configuration, but instead of activating it,
show what changes would be performed by the activation (i.e. by
<command>nixos-rebuild test</command>). For
instance, this command will print which systemd units would be
restarted. The list of changes is not guaranteed to be
complete.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -15,7 +15,7 @@
</author> </author>
<copyright> <copyright>
<year>2007-2013</year> <year>2007-2015</year>
<holder>Eelco Dolstra</holder> <holder>Eelco Dolstra</holder>
</copyright> </copyright>

View File

@ -32,6 +32,7 @@
<xi:include href="configuration/configuration.xml" /> <xi:include href="configuration/configuration.xml" />
<xi:include href="administration/running.xml" /> <xi:include href="administration/running.xml" />
<!-- <xi:include href="userconfiguration.xml" /> --> <!-- <xi:include href="userconfiguration.xml" /> -->
<xi:include href="development/development.xml" />
<xi:include href="release-notes/release-notes.xml" /> <xi:include href="release-notes/release-notes.xml" />
<appendix xml:id="ch-options"> <appendix xml:id="ch-options">

View File

@ -34,6 +34,14 @@
select="attr[@name = 'description']/string/@value" /> select="attr[@name = 'description']/string/@value" />
</para> </para>
<xsl:if test="attr[@name = 'type']">
<para>
<emphasis>Type:</emphasis>
<xsl:text> </xsl:text>
<xsl:apply-templates select="attr[@name = 'type']" mode="top" />
</para>
</xsl:if>
<xsl:if test="attr[@name = 'default']"> <xsl:if test="attr[@name = 'default']">
<para> <para>
<emphasis>Default:</emphasis> <emphasis>Default:</emphasis>

View File

@ -7,10 +7,12 @@
<title>Release Notes</title> <title>Release Notes</title>
<partintro> <partintro>
<para>This section lists the release notes for each stable version of NixOS.</para> <para>This section lists the release notes for each stable version of NixOS
and current unstable revision.</para>
</partintro> </partintro>
<xi:include href="rl-1410.xml" /> <xi:include href="rl-unstable.xml" />
<xi:include href="rl-1412.xml" />
<xi:include href="rl-1404.xml" /> <xi:include href="rl-1404.xml" />
<xi:include href="rl-1310.xml" /> <xi:include href="rl-1310.xml" />

View File

@ -1,22 +0,0 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-14.10">
<title>Release 14.10 (“Caterpillar”, 2014/10/??)</title>
<para>When upgrading from a previous release, please be aware of the
following incompatible changes:
<itemizedlist>
<listitem><para>The host side of a container virtual Ethernet pair
is now called <literal>ve-<replaceable>container-name</replaceable></literal>
rather than <literal>c-<replaceable>container-name</replaceable></literal>.</para></listitem>
</itemizedlist>
</para>
</chapter>

View File

@ -0,0 +1,177 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-14.12">
<title>Release 14.12 (“Caterpillar”, 2014/12/30)</title>
<para>In addition to numerous new and upgraded packages, this release has the following highlights:
<itemizedlist>
<listitem><para>Systemd has been updated to version 217, which has numerous
<link xlink:href="http://lists.freedesktop.org/archives/systemd-devel/2014-October/024662.html">improvements.</link></para></listitem>
<listitem><para><link xlink:href="http://thread.gmane.org/gmane.linux.distributions.nixos/15165">
Nix has been updated to 1.8.</link></para></listitem>
<listitem><para>NixOS is now based on Glibc 2.20.</para></listitem>
<listitem><para>KDE has been updated to 4.14.</para></listitem>
<listitem><para>The default Linux kernel has been updated to 3.14.</para></listitem>
<listitem><para>If <option>users.mutableUsers</option> is enabled (the
default), changes made to the declaration of a user or group will be
correctly realised when running <command>nixos-rebuild</command>. For
instance, removing a user specification from
<filename>configuration.nix</filename> will cause the actual user
account to be deleted. If <option>users.mutableUsers</option> is
disabled, it is no longer necessary to specify UIDs or GIDs; if
omitted, they are allocated dynamically.</para></listitem>
</itemizedlist></para>
<para>Following new services were added since the last release:
<itemizedlist>
<listitem><para><literal>atftpd</literal></para></listitem>
<listitem><para><literal>bosun</literal></para></listitem>
<listitem><para><literal>bspwm</literal></para></listitem>
<listitem><para><literal>chronos</literal></para></listitem>
<listitem><para><literal>collectd</literal></para></listitem>
<listitem><para><literal>consul</literal></para></listitem>
<listitem><para><literal>cpuminer-cryptonight</literal></para></listitem>
<listitem><para><literal>crashplan</literal></para></listitem>
<listitem><para><literal>dnscrypt-proxy</literal></para></listitem>
<listitem><para><literal>docker-registry</literal></para></listitem>
<listitem><para><literal>docker</literal></para></listitem>
<listitem><para><literal>etcd</literal></para></listitem>
<listitem><para><literal>fail2ban</literal></para></listitem>
<listitem><para><literal>fcgiwrap</literal></para></listitem>
<listitem><para><literal>fleet</literal></para></listitem>
<listitem><para><literal>fluxbox</literal></para></listitem>
<listitem><para><literal>gdm</literal></para></listitem>
<listitem><para><literal>geoclue2</literal></para></listitem>
<listitem><para><literal>gitlab</literal></para></listitem>
<listitem><para><literal>gitolite</literal></para></listitem>
<listitem><para><literal>gnome3.gnome-documents</literal></para></listitem>
<listitem><para><literal>gnome3.gnome-online-miners</literal></para></listitem>
<listitem><para><literal>gnome3.gvfs</literal></para></listitem>
<listitem><para><literal>gnome3.seahorse</literal></para></listitem>
<listitem><para><literal>hbase</literal></para></listitem>
<listitem><para><literal>i2pd</literal></para></listitem>
<listitem><para><literal>influxdb</literal></para></listitem>
<listitem><para><literal>kubernetes</literal></para></listitem>
<listitem><para><literal>liquidsoap</literal></para></listitem>
<listitem><para><literal>lxc</literal></para></listitem>
<listitem><para><literal>mailpile</literal></para></listitem>
<listitem><para><literal>mesos</literal></para></listitem>
<listitem><para><literal>mlmmj</literal></para></listitem>
<listitem><para><literal>monetdb</literal></para></listitem>
<listitem><para><literal>mopidy</literal></para></listitem>
<listitem><para><literal>neo4j</literal></para></listitem>
<listitem><para><literal>nsd</literal></para></listitem>
<listitem><para><literal>openntpd</literal></para></listitem>
<listitem><para><literal>opentsdb</literal></para></listitem>
<listitem><para><literal>openvswitch</literal></para></listitem>
<listitem><para><literal>parallels-guest</literal></para></listitem>
<listitem><para><literal>peerflix</literal></para></listitem>
<listitem><para><literal>phd</literal></para></listitem>
<listitem><para><literal>polipo</literal></para></listitem>
<listitem><para><literal>prosody</literal></para></listitem>
<listitem><para><literal>radicale</literal></para></listitem>
<listitem><para><literal>redmine</literal></para></listitem>
<listitem><para><literal>riemann</literal></para></listitem>
<listitem><para><literal>scollector</literal></para></listitem>
<listitem><para><literal>seeks</literal></para></listitem>
<listitem><para><literal>siproxd</literal></para></listitem>
<listitem><para><literal>strongswan</literal></para></listitem>
<listitem><para><literal>tcsd</literal></para></listitem>
<listitem><para><literal>teamspeak3</literal></para></listitem>
<listitem><para><literal>thermald</literal></para></listitem>
<listitem><para><literal>torque/mrom</literal></para></listitem>
<listitem><para><literal>torque/server</literal></para></listitem>
<listitem><para><literal>uhub</literal></para></listitem>
<listitem><para><literal>unifi</literal></para></listitem>
<listitem><para><literal>znc</literal></para></listitem>
<listitem><para><literal>zookeeper</literal></para></listitem>
</itemizedlist>
</para>
<para>When upgrading from a previous release, please be aware of the
following incompatible changes:
<itemizedlist>
<listitem><para>The default version of Apache httpd is now 2.4. If
you use the <option>extraConfig</option> option to pass literal
Apache configuration text, you may need to update it — see <link
xlink:href="http://httpd.apache.org/docs/2.4/upgrading.html">Apaches
documentation</link> for details. If you wish to continue to use
httpd 2.2, add the following line to your NixOS configuration:
<programlisting>
services.httpd.package = pkgs.apacheHttpd_2_2;
</programlisting>
</para></listitem>
<listitem><para>PHP 5.3 has been removed because it is no longer
supported by the PHP project. A <link
xlink:href="http://php.net/migration54">migration guide</link> is
available.</para></listitem>
<listitem><para>The host side of a container virtual Ethernet pair
is now called <literal>ve-<replaceable>container-name</replaceable></literal>
rather than <literal>c-<replaceable>container-name</replaceable></literal>.</para></listitem>
<listitem><para>GNOME 3.10 support has been dropped. The default GNOME version is now 3.12.</para></listitem>
<listitem><para>VirtualBox has been upgraded to 4.3.20 release. Users
may be required to run <command>rm -rf /tmp/.vbox*</command>. The line
<literal>imports = [ &lt;nixpkgs/nixos/modules/programs/virtualbox.nix&gt; ]</literal> is
no longer necessary, use <literal>services.virtualboxHost.enable =
true</literal> instead.
</para>
<para>Also, hardening mode is now enabled by default, which means that unless you want to use
USB support, you no longer need to be a member of the <literal>vboxusers</literal> group.
</para></listitem>
<listitem><para>Chromium has been updated to 39.0.2171.65. <option>enablePepperPDF</option> is now enabled by default.
<literal>chromium*Wrapper</literal> packages no longer exist, because upstream removed NSAPI support.
<literal>chromium-stable</literal> has been renamed to <literal>chromium</literal>.
</para></listitem>
<listitem><para>Python packaging documentation is now part of nixpkgs manual. To override
the python packages available to a custom python you now use <literal>pkgs.pythonFull.buildEnv.override</literal>
instead of <literal>pkgs.pythonFull.override</literal>.
</para></listitem>
<listitem><para><literal>boot.resumeDevice = "8:6"</literal> is no longer supported. Most users will
want to leave it undefined, which takes the swap partitions automatically. There is an evaluation
assertion to ensure that the string starts with a slash.
</para></listitem>
<listitem><para>The system-wide default timezone for NixOS installations
changed from <literal>CET</literal> to <literal>UTC</literal>. To choose
a different timezone for your system, configure
<literal>time.timeZone</literal> in
<literal>configuration.nix</literal>. A fairly complete list of possible
values for that setting is available at <link
xlink:href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"/>.</para></listitem>
<listitem><para>GNU screen has been updated to 4.2.1, which breaks
the ability to connect to sessions created by older versions of
screen.</para></listitem>
<listitem><para>The Intel GPU driver was updated to the 3.x prerelease
version (used by most distributions) and supports DRI3
now.</para></listitem>
</itemizedlist>
</para>
</chapter>

View File

@ -0,0 +1,41 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
version="5.0"
xml:id="sec-release-unstable">
<title>Unstable revision</title>
<para>In addition to numerous new and upgraded packages, this release has the following highlights:
<!--<itemizedlist>
</itemizedlist>-->
</para>
<para>Following new services were added since the last release:
<!--<itemizedlist>
</itemizedlist>-->
</para>
<para>When upgrading from a previous release, please be aware of the
following incompatible changes:
<itemizedlist>
<listitem><para>Steam now doesn't need root rights to work. Instead of using
<literal>*-steam-chrootenv</literal>, you should now just run <literal>steam</literal>.
<literal>steamChrootEnv</literal> package was renamed to <literal>steam</literal>,
and old <literal>steam</literal> package -- to <literal>steamOriginal</literal>.
</para></listitem>
<listitem><para>CMPlayer has been renamed to bomi upstream. Package <literal>cmplayer</literal>
was accordingly renamed to <literal>bomi</literal>
</para></listitem>
</itemizedlist>
</para>
</chapter>

View File

@ -1,16 +0,0 @@
This file should become a nix expression. (see modules/installer/tools/tools.nix)
you need to:
- download the latest jQuery from and copy it to chrome/content:
http://code.jquery.com/jquery-1.5.2.js
- install 'xulrunner' with nix:
nix-env -Ai nixpkgs_sys.firefox40Pkgs.xulrunner
- make sure nixos-option in your path
- have /etc/nixos/nixpkgs
- have /etc/nixos/nixos
run it:
- xulrunner /etc/nixos/nixos/gui/application.ini -jsconsole

View File

@ -1,36 +0,0 @@
[App]
;
; This field specifies your organization's name. This field is recommended,
; but optional.
Vendor=NixOS
;
; This field specifies your application's name. This field is required.
Name=NixOS-gui
;
; This field specifies your application's version. This field is optional.
Version=0.1
;
; This field specifies your application's build ID (timestamp). This field is
; required.
BuildID=20110424
;
; This field specifies a compact copyright notice for your application. This
; field is optional.
;Copyright=
;
; This ID is just an example. Every XUL app ought to have it's own unique ID.
; You can use the microsoft "guidgen" or "uuidgen" tools, or go on
; irc.mozilla.org and /msg botbot uuid. This field is optional.
;ID=
[Gecko]
;
; This field is required. It specifies the minimum Gecko version that this
; application requires.
MinVersion=1.9a5
;
; This field is optional. It specifies the maximum Gecko version that this
; application requires. It should be specified if your application uses
; unfrozen interfaces.
MaxVersion=2.*

View File

@ -1 +0,0 @@
manifest chrome/chrome.manifest

View File

@ -1 +0,0 @@
content nixos-gui content/

View File

@ -1,137 +0,0 @@
function inspect(obj, maxLevels, level)
{
var str = '', type, msg;
// Start Input Validations
// Don't touch, we start iterating at level zero
if(level == null) level = 0;
// At least you want to show the first level
if(maxLevels == null) maxLevels = 1;
if(maxLevels < 1)
return '<font color="red">Error: Levels number must be > 0</font>';
// We start with a non null object
if(obj == null)
return '<font color="red">Error: Object <b>NULL</b></font>';
// End Input Validations
// Each Iteration must be indented
str += '<ul>';
// Start iterations for all objects in obj
for(property in obj)
{
try
{
// Show "property" and "type property"
type = typeof(obj[property]);
str += '<li>(' + type + ') ' + property +
( (obj[property]==null)?(': <b>null</b>'):('')) + '</li>';
// We keep iterating if this property is an Object, non null
// and we are inside the required number of levels
if((type == 'object') && (obj[property] != null) && (level+1 < maxLevels))
str += inspect(obj[property], maxLevels, level+1);
}
catch(err)
{
// Is there some properties in obj we can't access? Print it red.
if(typeof(err) == 'string') msg = err;
else if(err.message) msg = err.message;
else if(err.description) msg = err.description;
else msg = 'Unknown';
str += '<li><font color="red">(Error) ' + property + ': ' + msg +'</font></li>';
}
}
// Close indent
str += '</ul>';
return str;
}
// Run xulrunner application.ini -jsconsole -console, to see messages.
function log(str)
{
Components.classes['@mozilla.org/consoleservice;1']
.getService(Components.interfaces.nsIConsoleService)
.logStringMessage(str);
}
function makeTempFile(prefix)
{
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("TmpD", Components.interfaces.nsIFile);
file.append(prefix || "xulrunner");
file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0664);
return file;
}
function writeToFile(file, data)
{
// file is nsIFile, data is a string
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
// use 0x02 | 0x10 to open file for appending.
foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate
foStream.write(data, data.length);
foStream.close();
}
function readFromFile(file)
{
// |file| is nsIFile
var data = "";
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
.createInstance(Components.interfaces.nsIScriptableInputStream);
fstream.init(file, -1, 0, 0);
sstream.init(fstream);
var str = sstream.read(4096);
while (str.length > 0) {
data += str;
str = sstream.read(4096);
}
sstream.close();
fstream.close();
return data;
}
function runProgram(commandLine)
{
// create an nsILocalFile for the executable
var file = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
file.initWithPath("/bin/sh");
// create an nsIProcess
var process = Components.classes["@mozilla.org/process/util;1"]
.createInstance(Components.interfaces.nsIProcess);
process.init(file);
// Run the process.
// If first param is true, calling thread will be blocked until
// called process terminates.
// Second and third params are used to pass command-line arguments
// to the process.
var args = ["-c", commandLine];
process.run(true, args, args.length);
}
// only for testing...
function testIO()
{
var f = makeTempFile();
writeToFile(f, "essai\ntest");
alert(readFromFile(f));
runProgram("zenity --info");
}

View File

@ -1,70 +0,0 @@
// global variables.
var gNixOS;
var gOptionView;
/*
var gProgressBar;
function setProgress(current, max)
{
if (gProgressBar) {
gProgressBar.value = 100 * current / max;
log("progress: " + gProgressBar.value + "%");
}
else
log("unknow progress bar");
}
*/
function updateTextbox(id, value)
{
// setting the height cause an overflow which resize the textbox to its
// content due to its onoverflow attribute.
$(id).attr("value", value).attr("height", 1);
};
function updatePanel(options)
{
log("updatePanel: " + options.length);
if (options.length == 0)
return;
// FIXME: ignore the rest of the selection for now.
var o = options[0];
$("#name").attr("label", o.path);
if (o.typename != null)
$("#typename").attr("label", o.typename);
else
$("#typename").attr("label", "");
$("#desc").text(o.description);
if (o.value != null)
updateTextbox("#val", o.value);
else
updateTextbox("#val", "");
if (o.defaultValue != null)
updateTextbox("#def", o.defaultValue);
else
updateTextbox("#def", "");
if (o.example != null)
updateTextbox("#exp", o.example);
else
updateTextbox("#exp", "");
updateTextbox("#decls", o.declarations.join("\n"));
updateTextbox("#defs", o.definitions.join("\n"));
}
function onload()
{
var optionTree = document.getElementById("option-tree");
// gProgressBar = document.getElementById("progress-bar");
// setProgress(0, 1);
gNixOS = new NixOS();
gOptionView = new OptionView(gNixOS.option, updatePanel);
optionTree.view = gOptionView;
}

View File

@ -1,63 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE window>
<!-- To edit this file I recommend you to use:
http://xulfr.org/outils/xulediteur.xul
-->
<window
id = "nixos-gui"
title = "NixOS gui"
width = "800"
height = "600"
xmlns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="jquery-1.5.2.js"/>
<script src="io.js"/>
<script src="nixos.js"/>
<script src="optionView.js"/>
<script src="main.js"/>
<hbox flex="1">
<vbox width="250">
<tree flex="1" id="option-tree" persist="height" onselect="gOptionView.selectionChanged()">
<treecols>
<treecol persist="hidden width" flex="9" id="opt-name"
label="Option" primary="true"/>
<!-- Uncomment the following column to see the number of option
printed below each options. -->
<!--
<treecol persist="hidden width" flex="1" id="dbg-size"
label="sz"/>
-->
</treecols>
<treechildren id="first-child" flex="1"/>
</tree>
</vbox>
<vbox flex="3" style="overflow: auto">
<caption id="name" label=""/>
<caption id="typename" label=""/>
<separator/>
<description id="desc" hidden="false"></description>
<separator/>
<caption label="Value:"/>
<textbox id="val" readonly="true" multiline="true" value=""
class="plain" hidden="false" onoverflow="this.height =
this.inputField.scrollHeight;" />
<separator/>
<caption label="Default:"/>
<textbox id="def" readonly="true" multiline="true" value="" class="plain" hidden="false" onoverflow="this.height = this.inputField.scrollHeight;" />
<separator/>
<caption label="Example:"/>
<textbox id="exp" readonly="true" multiline="true" value="" class="plain" hidden="false" onoverflow="this.height = this.inputField.scrollHeight;" />
<separator/>
<caption label="Declarations:"/>
<textbox id="decls" readonly="true" multiline="true" value="" class="plain" hidden="false" onoverflow="this.height = this.inputField.scrollHeight;" />
<separator/>
<caption label="Definitions:"/>
<textbox id="defs" readonly="true" multiline="true" value=""
class="plain" hidden="false" onoverflow="this.height = this.inputField.scrollHeight;" />
</vbox>
</hbox>
<!-- <progressmeter id="progress-bar" value="0%"/> -->
</window>

View File

@ -1,255 +0,0 @@
function NixOS () {
var env = Components.classes["@mozilla.org/process/environment;1"].
getService(Components.interfaces.nsIEnvironment);
if (env.exists("NIXOS"))
this.nixos = env.get("NIXOS");
if (env.exists("NIXOS_CONFIG"))
this.config = env.get("NIXOS_CONFIG");
if (env.exists("NIXPKGS"))
this.nixpkgs = env.get("NIXPKGS");
if (env.exists("mountPoint"))
this.root = env.get("mountPoint");
if (env.exists("NIXOS_OPTION"))
this.optionBin = env.get("NIXOS_OPTION");
this.option = new Option("options", this, null);
};
NixOS.prototype = {
root: "",
nixos: "/etc/nixos/nixos",
nixpkgs: "/etc/nixos/nixpkgs",
config: "/etc/nixos/configuration.nix",
instantiateBin: "/run/current-system/sw/bin/nix-instantiate",
optionBin: "/run/current-system/sw/bin/nixos-option",
tmpFile: "nixos-gui",
option: null
};
function Option (name, context, parent) {
this.name = name;
this.context_ = context;
if (parent == null)
this.path = "";
else if (parent.path == "")
this.path = name;
else
this.path = parent.path + "." + name;
};
Option.prototype = {
load: function () {
var env = "";
env += "'NIXOS=" + this.context_.root + this.context_.nixos + "' ";
env += "'NIXOS_PKGS=" + this.context_.root + this.context_.nixpkgs + "' ";
env += "'NIXOS_CONFIG=" + this.context_.config + "' ";
var out = makeTempFile(this.context_.tmpFile);
var prog = this.context_.optionBin + " 2>&1 >" + out.path + " ";
var args = " --xml " + this.path;
runProgram(/*env + */ prog + args);
var xml = readFromFile(out);
out.remove(false);
// jQuery does a stack overflow when converting a huge XML to a DOM.
var dom = DOMParser().parseFromString(xml, "text/xml");
var xmlAttrs = $("expr > attrs > attr", dom);
this.isOption = xmlAttrs.first().attr("name") == "_isOption";
if (!this.isOption)
this.loadSubOptions(xmlAttrs);
else
this.loadOption(xmlAttrs);
this.isLoaded = true;
},
loadSubOptions: function (xmlAttrs) {
var cur = this;
var attrs = new Array();
xmlAttrs.each(
function (index) {
var name = $(this).attr("name");
var attr = new Option(name, cur.context_, cur);
attrs.push(attr);
}
);
this.subOptions = attrs;
},
optionAttributeMap: {
_isOption: function (cur, v) { },
value: function (cur, v) { cur.value = xml2nix($(v).children().first()); },
default: function (cur, v) { cur.defaultValue = xml2nix($(v).children().first()); },
example: function (cur, v) { cur.example = xml2nix($(v).children().first()); },
description: function (cur, v) { cur.description = this.string(v); },
typename: function (cur, v) { cur.typename = this.string(v); },
options: function (cur, v) { cur.loadSubOptions($("attrs", v).children()); },
declarations: function (cur, v) { cur.declarations = this.pathList(v); },
definitions: function (cur, v) { cur.definitions = this.pathList(v); },
string: function (v) {
return $(v).children("string").first().attr("value");
},
pathList: function (v) {
var list = [];
$(v).children("list").first().children().each(
function (idx) {
list.push($(this).attr("value"));
}
);
return list;
}
},
loadOption: function (attrs) {
var cur = this;
attrs.each(
function (index) {
var name = $(this).attr("name");
log("loadOption: " + name);
cur.optionAttributeMap[name](cur, this);
}
);
},
// keep the context under which this option has been used.
context_: null,
// name of the option.
name: "",
// result of nixos-option.
value: null,
typename: null,
defaultValue: null,
example: null,
description: "",
declarations: [],
definitions: [],
// path to reach this option
path: "",
// list of options accessible from here.
isLoaded: false,
isOption: false,
subOptions: []
};
var xml2nix_pptable = {
attrs: function (node, depth, pp) {
var children = node.children().not(
function () {
var name = $(this).attr("name");
return name.charAt(0) == "_";
}
);
var c = 0;
var out = "";
out += "{";
depth += 1;
children.each(
function (idx) {
c += 1;
out += pp.indent(depth);
out += pp.dispatch($(this), depth, pp);
}
);
depth -= 1;
if (c > 0)
out += this.indent(depth);
else
out += " ";
out += "}";
return out;
},
list: function (node, depth, pp) {
var children = node.children();
var c = 0;
var out = "";
out += "[";
depth += 1;
children.each(
function (idx) {
c += 1;
out += pp.indent(depth);
out += pp.dispatch($(this), depth, pp);
}
);
depth -= 1;
if (c > 0)
out += this.indent(depth);
else
out += " ";
out += "]";
return out;
},
attr: function (node, depth, pp) {
var name = node.attr("name");
var out = "";
var val = "";
out += name + " = ";
depth += 1;
val = pp.dispatch(node.children().first(), depth, pp);
out += val;
depth -= 1;
out += ";";
return out;
},
string: function (node, depth, pp) {
return "\"" + node.attr("value") + "\"";
},
path: function (node, depth, pp) {
return node.attr("value");
},
bool: function (node, depth, pp) {
return node.attr("value");
},
"int": function (node, depth, pp) {
return node.attr("value");
},
null: function (node, depth, pp) {
return "null";
},
derivation: function (node, depth, pp) {
return "<derivation>";
},
function: function (node, depth, pp) {
return "<function>";
},
unevaluated: function (node, depth, pp) {
return "<unevaluated>";
},
dispatch: function (node, depth, pp) {
for (var key in pp)
{
if(node.is(key))
{
// log(this.indent(depth) + "dispatch: " + key);
var out = pp[key](node, depth, pp);
// log(this.indent(depth) + "dispatch: => " + out);
return out;
}
}
return "<dispatch-error>";
},
indent: function (depth) {
var ret = "\n";
while (depth--)
ret += " ";
return ret;
}
};
function xml2nix(node) {
var depth = 0;
var pp = xml2nix_pptable;
var out = pp.dispatch(node, depth, pp);
// log("pretty:\n" + out);
return out;
}

View File

@ -1,242 +0,0 @@
// extend NixOS options to handle the Tree View. Should be better to keep a
// separation of concern here.
Option.prototype.tv_opened = false;
Option.prototype.tv_size = 1;
Option.prototype.tv_open = function () {
this.tv_opened = true;
this.tv_size = 1;
// load an option if it is not loaded yet, and initialize them to be
// read by the Option view.
if (!this.isLoaded)
this.load();
// If this is not an option, then add it's lits of sub-options size.
if (!this.isOption)
{
for (var i = 0; i < this.subOptions.length; i++)
this.tv_size += this.subOptions[i].tv_size;
}
};
Option.prototype.tv_close = function () {
this.tv_opened = false;
this.tv_size = 1;
};
function OptionView (root, selCallback) {
root.tv_open();
this.rootOption = root;
this.selCallback = selCallback;
}
OptionView.prototype = {
rootOption: null,
selCallback: null,
// This function returns the path to option which is at the specified row.
reach_cache: null,
reachRow: function (row) {
var o = this.rootOption; // Current option.
var r = 0; // Number of rows traversed.
var c = 0; // Child index.
var path = [{ row: r, opt: o }]; // new Array();
// hypothesis: this.rootOption.tv_size is always open and bigger than
// Use the previous returned value to avoid making to many checks and to
// optimize for frequent access of near rows.
if (this.reach_cache != null)
{
for (var i = this.reach_cache.length - 2; i >= 0; i--) {
var p = this.reach_cache[i];
// If we will have to go the same path.
if (row >= p.row && row < p.row + p.opt.tv_size)
{
path.unshift(p);
r = path[0].row;
o = path[0].opt;
}
else
break;
};
}
while (r != row)
{
// Go deeper in the child which contains the requested row. The
// tv_size contains the size of the tree starting from each option.
c = 0;
while (c < o.subOptions.length && r + o.subOptions[c].tv_size < row)
{
r += o.subOptions[c].tv_size;
c += 1;
}
if (c < o.subOptions.length && r + o.subOptions[c].tv_size >= row)
{
// Count the current option as a row.
o = o.subOptions[c];
r += 1;
}
else
alert("WTF: " + o.name + " ask: " + row + " children: " + o.subOptions + " c: " + c);
path.unshift({ row: r, opt: o });
}
this.reach_cache = path;
return path;
},
// needs to return true if there is a /row/ at the same level /after/ a
// given row.
hasNextSibling: function(row, after) {
log("sibling " + row + " after " + after);
var path = reachRow(row);
if (path.length > 1)
{
var last = path[1].row + path[1].opt.tv_size;
// Has a next sibling if the row is not over the size of the
// parent and if the current one is not the last child.
return after + 1 < last && path[0].row + path[0].opt.tv_size < last;
}
else
// The top-level option has no sibling.
return false;
},
// Does the current row contain any sub-options?
isContainer: function(row) {
return !this.reachRow(row)[0].opt.isOption;
},
isContainerEmpty: function(row) {
return this.reachRow(row)[0].opt.subOptions.length == 0;
},
isContainerOpen: function(row) {
return this.reachRow(row)[0].opt.tv_opened;
},
// Open or close an option.
toggleOpenState: function (row) {
var path = this.reachRow(row);
var delta = -path[0].opt.tv_size;
if (path[0].opt.tv_opened)
path[0].opt.tv_close();
else
path[0].opt.tv_open();
delta += path[0].opt.tv_size;
// Parents are alreay opened, but we need to update the tv_size
// counters. Thus we have to invalidate the reach cache.
this.reach_cache = null;
for (var i = 1; i < path.length; i++)
path[i].opt.tv_open();
this.tree.rowCountChanged(row + 1, delta);
},
// Return the identation level of the option at the line /row/. The
// top-level level is 0.
getLevel: function(row) {
return this.reachRow(row).length - 1;
},
// Obtain the index of a parent row. If there is no parent row,
// returns -1.
getParentIndex: function(row) {
var path = this.reachRow(row);
if (path.length > 1)
return path[1].row;
else
return -1;
},
// Return the content of each row base on the column name.
getCellText: function(row, column) {
if (column.id == "opt-name")
return this.reachRow(row)[0].opt.name;
if (column.id == "dbg-size")
return this.reachRow(row)[0].opt.tv_size;
return "";
},
// We have no column with images.
getCellValue: function(row, column) { },
isSelectable: function(row, column) { return true; },
// Get the selection out of the tree and give options to the call back
// function.
selectionChanged: function() {
if (this.selCallback == null)
return;
var opts = [];
var start = new Object();
var end = new Object();
var numRanges = this.tree.view.selection.getRangeCount();
for (var t = 0; t < numRanges; t++) {
this.tree.view.selection.getRangeAt(t,start,end);
for (var v = start.value; v <= end.value; v++) {
var opt = this.reachRow(v)[0].opt;
if (!opt.isLoaded)
opt.load();
if (opt.isOption)
opts.push(opt);
// FIXME: no need to make things slowing down, because our current
// callback do not handle multiple option display.
if (!opts.empty)
break;
}
// FIXME: no need to make things slowing down, because our current
// callback do not handle multiple option display.
if (!opts.empty)
break;
}
if (!opts.empty)
this.selCallback(opts);
},
set rowCount(c) { throw "rowCount is a readonly property"; },
get rowCount() { return this.rootOption.tv_size; },
// refuse drag-n-drop of options.
canDrop: function (index, orientation, dataTransfer) { return false; },
drop: function (index, orientation, dataTransfer) { },
// ?
getCellProperties: function(row, column, prop) { },
getColumnProperties: function(column, prop) { },
getRowProperties: function(row, prop) { },
getImageSrc: function(row, column) { },
// No progress columns are used.
getProgressMode: function(row, column) { },
// Do not add options yet.
isEditable: function(row, column) { return false; },
setCellValue: function(row, column, value) { },
setCellText: function(row, column, value) { },
// ...
isSeparator: function(index) { return false; },
isSorted: function() { return false; },
performAction: function(action) { },
performActionOnCell: function(action, row, column) { },
performActionOnRow: function(action, row) { }, // ??
// ??
cycleCell: function (row, col) { },
cycleHeader: function(col) { },
selection: null,
tree: null,
setTree: function(tree) { this.tree = tree; }
};

View File

@ -1,154 +0,0 @@
const nsIAppShellService = Components.interfaces.nsIAppShellService;
const nsISupports = Components.interfaces.nsISupports;
const nsICategoryManager = Components.interfaces.nsICategoryManager;
const nsIComponentRegistrar = Components.interfaces.nsIComponentRegistrar;
const nsICommandLine = Components.interfaces.nsICommandLine;
const nsICommandLineHandler = Components.interfaces.nsICommandLineHandler;
const nsIFactory = Components.interfaces.nsIFactory;
const nsIModule = Components.interfaces.nsIModule;
const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
// CHANGEME: to the chrome URI of your extension or application
const CHROME_URI = "chrome://nixos-gui/content/myviewer.xul";
// CHANGEME: change the contract id, CID, and category to be unique
// to your application.
const clh_contractID = "@mozilla.org/commandlinehandler/general-startup;1?type=myapp";
// use uuidgen to generate a unique ID
const clh_CID = Components.ID("{2991c315-b871-42cd-b33f-bfee4fcbf682}");
// category names are sorted alphabetically. Typical command-line handlers use a
// category that begins with the letter "m".
const clh_category = "m-myapp";
/**
* Utility functions
*/
/**
* Opens a chrome window.
* @param aChromeURISpec a string specifying the URI of the window to open.
* @param aArgument an argument to pass to the window (may be null)
*/
function openWindow(aChromeURISpec, aArgument)
{
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
getService(Components.interfaces.nsIWindowWatcher);
ww.openWindow(null, aChromeURISpec, "_blank",
"chrome,menubar,toolbar,status,resizable,dialog=no",
aArgument);
}
/**
* The XPCOM component that implements nsICommandLineHandler.
* It also implements nsIFactory to serve as its own singleton factory.
*/
const myAppHandler = {
/* nsISupports */
QueryInterface : function clh_QI(iid)
{
if (iid.equals(nsICommandLineHandler) ||
iid.equals(nsIFactory) ||
iid.equals(nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
/* nsICommandLineHandler */
handle : function clh_handle(cmdLine)
{
openWindow(CHROME_URI, cmdLine);
cmdLine.preventDefault = true;
},
// CHANGEME: change the help info as appropriate, but
// follow the guidelines in nsICommandLineHandler.idl
// specifically, flag descriptions should start at
// character 24, and lines should be wrapped at
// 72 characters with embedded newlines,
// and finally, the string should end with a newline
helpInfo : " <filename> Open the file in the viewer\n",
/* nsIFactory */
createInstance : function clh_CI(outer, iid)
{
if (outer != null)
throw Components.results.NS_ERROR_NO_AGGREGATION;
return this.QueryInterface(iid);
},
lockFactory : function clh_lock(lock)
{
/* no-op */
}
};
/**
* The XPCOM glue that implements nsIModule
*/
const myAppHandlerModule = {
/* nsISupports */
QueryInterface : function mod_QI(iid)
{
if (iid.equals(nsIModule) ||
iid.equals(nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
/* nsIModule */
getClassObject : function mod_gch(compMgr, cid, iid)
{
if (cid.equals(clh_CID))
return myAppHandler.QueryInterface(iid);
throw Components.results.NS_ERROR_NOT_REGISTERED;
},
registerSelf : function mod_regself(compMgr, fileSpec, location, type)
{
compMgr.QueryInterface(nsIComponentRegistrar);
compMgr.registerFactoryLocation(clh_CID,
"myAppHandler",
clh_contractID,
fileSpec,
location,
type);
var catMan = Components.classes["@mozilla.org/categorymanager;1"].
getService(nsICategoryManager);
catMan.addCategoryEntry("command-line-handler",
clh_category,
clh_contractID, true, true);
},
unregisterSelf : function mod_unreg(compMgr, location, type)
{
compMgr.QueryInterface(nsIComponentRegistrar);
compMgr.unregisterFactoryLocation(clh_CID, location);
var catMan = Components.classes["@mozilla.org/categorymanager;1"].
getService(nsICategoryManager);
catMan.deleteCategoryEntry("command-line-handler", clh_category);
},
canUnload : function (compMgr)
{
return true;
}
};
/* The NSGetModule function is the magic entry point that XPCOM uses to find what XPCOM objects
* this component provides
*/
function NSGetModule(comMgr, fileSpec)
{
return myAppHandlerModule;
}

View File

@ -1,11 +0,0 @@
pref("toolkit.defaultChromeURI", "chrome://nixos-gui/content/myviewer.xul");
pref("general.useragent.extra.myviewer", "NixOS gui/0.0");
/* debugging prefs */
pref("browser.dom.window.dump.enabled", true); // enable output to stderr
pref("javascript.options.showInConsole", true); // show javascript errors from chrome: files in the jsconsole
pref("javascript.options.strict", true); // show javascript strict warnings in the jsconsole
/* disable xul cache so that modifications to chrome: files apply without restarting xulrunner */
pref("nglayout.debug.disable_xul_cache", true);
pref("nglayout.debug.disable_xul_fastload", true);

View File

@ -48,10 +48,11 @@ rec {
let let
interfacesNumbered = zipTwoLists config.virtualisation.vlans (range 1 255); interfacesNumbered = zipTwoLists config.virtualisation.vlans (range 1 255);
interfaces = flip map interfacesNumbered ({ first, second }: interfaces = flip map interfacesNumbered ({ first, second }:
nameValuePair "eth${toString second}" nameValuePair "eth${toString second}" { ip4 =
{ ipAddress = "192.168.${toString first}.${toString m.second}"; [ { address = "192.168.${toString first}.${toString m.second}";
subnetMask = "255.255.255.0"; prefixLength = 24;
}); } ];
});
in in
{ key = "ip-address"; { key = "ip-address";
config = config =
@ -60,7 +61,7 @@ rec {
networking.interfaces = listToAttrs interfaces; networking.interfaces = listToAttrs interfaces;
networking.primaryIPAddress = networking.primaryIPAddress =
optionalString (interfaces != []) (head interfaces).value.ipAddress; optionalString (interfaces != []) (head (head interfaces).value.ip4).address;
# Put the IP addresses of all VMs in this machine's # Put the IP addresses of all VMs in this machine's
# /etc/hosts file. If a machine has multiple # /etc/hosts file. If a machine has multiple
@ -69,7 +70,7 @@ rec {
# virtualisation.vlans option). # virtualisation.vlans option).
networking.extraHosts = flip concatMapStrings machines networking.extraHosts = flip concatMapStrings machines
(m': let config = (getAttr m' nodes).config; in (m': let config = (getAttr m' nodes).config; in
optionalString (m.first != m' && config.networking.primaryIPAddress != "") optionalString (config.networking.primaryIPAddress != "")
("${config.networking.primaryIPAddress} " + ("${config.networking.primaryIPAddress} " +
"${config.networking.hostName}\n")); "${config.networking.hostName}\n"));

View File

@ -2,26 +2,51 @@
# configuration object (`config') from which we can retrieve option # configuration object (`config') from which we can retrieve option
# values. # values.
{ system ? builtins.currentSystem # !!! Please think twice before adding to this argument list!
, pkgs ? null # Ideally eval-config.nix would be an extremely thin wrapper
, baseModules ? import ../modules/module-list.nix # around lib.evalModules, so that modular systems that have nixos configs
, extraArgs ? {} # as subcomponents (e.g. the container feature, or nixops if network
# expressions are ever made modular at the top level) can just use
# types.submodule instead of using eval-config.nix
{ # !!! system can be set modularly, would be nice to remove
system ? builtins.currentSystem
, # !!! is this argument needed any more? The pkgs argument can
# be set modularly anyway.
pkgs ? null
, # !!! what do we gain by making this configurable?
baseModules ? import ../modules/module-list.nix
, # !!! See comment about args in lib/modules.nix
extraArgs ? {}
, modules , modules
, check ? true , # !!! See comment about check in lib/modules.nix
check ? true
, prefix ? [] , prefix ? []
, lib ? import ../../lib
}: }:
let extraArgs_ = extraArgs; pkgs_ = pkgs; system_ = system; in let extraArgs_ = extraArgs; pkgs_ = pkgs; system_ = system;
extraModules = let e = builtins.getEnv "NIXOS_EXTRA_MODULE_PATH";
in if e == "" then [] else [(import (builtins.toPath e))];
in
rec { let
pkgsModule = rec {
_file = ./eval-config.nix;
key = _file;
config = {
nixpkgs.system = lib.mkDefault system_;
_module.args.pkgs = lib.mkIf (pkgs_ != null) (lib.mkForce pkgs_);
};
};
in rec {
# Merge the option definitions in all modules, forming the full # Merge the option definitions in all modules, forming the full
# system configuration. # system configuration.
inherit (pkgs.lib.evalModules { inherit (lib.evalModules {
inherit prefix; inherit prefix check;
modules = modules ++ baseModules; modules = modules ++ extraModules ++ baseModules ++ [ pkgsModule ];
args = extraArgs; args = extraArgs;
check = check && options.environment.checkConfigurationOptions.value;
}) config options; }) config options;
# These are the extra arguments passed to every module. In # These are the extra arguments passed to every module. In
@ -32,40 +57,8 @@ rec {
# the 64-bit package anyway. However, it would be cleaner to respect # the 64-bit package anyway. However, it would be cleaner to respect
# nixpkgs.config here. # nixpkgs.config here.
extraArgs = extraArgs_ // { extraArgs = extraArgs_ // {
inherit pkgs modules baseModules; inherit modules baseModules;
modulesPath = ../modules;
pkgs_i686 = import ./nixpkgs.nix { system = "i686-linux"; config.allowUnfree = true; };
utils = import ./utils.nix pkgs;
}; };
# Import Nixpkgs, allowing the NixOS option nixpkgs.config to inherit (config._module.args) pkgs;
# specify the Nixpkgs configuration (e.g., to set package options
# such as firefox.enableGeckoMediaPlayer, or to apply global
# overrides such as changing GCC throughout the system), and the
# option nixpkgs.system to override the platform type. This is
# tricky, because we have to prevent an infinite recursion: "pkgs"
# is passed as an argument to NixOS modules, but the value of "pkgs"
# depends on config.nixpkgs.config, which we get from the modules.
# So we call ourselves here with "pkgs" explicitly set to an
# instance that doesn't depend on nixpkgs.config.
pkgs =
if pkgs_ != null
then pkgs_
else import ./nixpkgs.nix (
let
system = if nixpkgsOptions.system != "" then nixpkgsOptions.system else system_;
nixpkgsOptions = (import ./eval-config.nix {
inherit system extraArgs modules prefix;
# For efficiency, leave out most NixOS modules; they don't
# define nixpkgs.config, so it's pointless to evaluate them.
baseModules = [ ../modules/misc/nixpkgs.nix ../modules/config/no-x-libs.nix ];
pkgs = import ./nixpkgs.nix { system = system_; config = {}; };
check = false;
}).config.nixpkgs;
in
{
inherit system;
inherit (nixpkgsOptions) config;
});
} }

View File

@ -1,4 +1,4 @@
{ stdenv, perl, cdrkit, pathsFromGraph { stdenv, perl, pathsFromGraph, xorriso, syslinux
, # The file name of the resulting ISO image. , # The file name of the resulting ISO image.
isoName ? "cd.iso" isoName ? "cd.iso"
@ -22,12 +22,18 @@
, # Whether this should be an efi-bootable El-Torito CD. , # Whether this should be an efi-bootable El-Torito CD.
efiBootable ? false efiBootable ? false
, # Wheter this should be an hybrid CD (bootable from USB as well as CD).
usbBootable ? false
, # The path (in the ISO file system) of the boot image. , # The path (in the ISO file system) of the boot image.
bootImage ? "" bootImage ? ""
, # The path (in the ISO file system) of the efi boot image. , # The path (in the ISO file system) of the efi boot image.
efiBootImage ? "" efiBootImage ? ""
, # The path (outside the ISO file system) of the isohybrid-mbr image.
isohybridMbrImage ? ""
, # Whether to compress the resulting ISO image with bzip2. , # Whether to compress the resulting ISO image with bzip2.
compressImage ? false compressImage ? false
@ -38,13 +44,14 @@
assert bootable -> bootImage != ""; assert bootable -> bootImage != "";
assert efiBootable -> efiBootImage != ""; assert efiBootable -> efiBootImage != "";
assert usbBootable -> isohybridMbrImage != "";
stdenv.mkDerivation { stdenv.mkDerivation {
name = "iso9660-image"; name = "iso9660-image";
builder = ./make-iso9660-image.sh; builder = ./make-iso9660-image.sh;
buildInputs = [perl cdrkit]; buildInputs = [perl xorriso syslinux];
inherit isoName bootable bootImage compressImage volumeID pathsFromGraph efiBootImage efiBootable; inherit isoName bootable bootImage compressImage volumeID pathsFromGraph efiBootImage efiBootable isohybridMbrImage usbBootable;
# !!! should use XML. # !!! should use XML.
sources = map (x: x.source) contents; sources = map (x: x.source) contents;

View File

@ -13,6 +13,20 @@ stripSlash() {
if test "${res:0:1}" = /; then res=${res:1}; fi if test "${res:0:1}" = /; then res=${res:1}; fi
} }
# Escape potential equal signs (=) with backslash (\=)
escapeEquals() {
echo "$1" | sed -e 's/\\/\\\\/g' -e 's/=/\\=/g'
}
# Queues an file/directory to be placed on the ISO.
# An entry consists of a local source path (2) and
# a destination path on the ISO (1).
addPath() {
target="$1"
source="$2"
echo "$(escapeEquals "$target")=$(escapeEquals "$source")" >> pathlist
}
stripSlash "$bootImage"; bootImage="$res" stripSlash "$bootImage"; bootImage="$res"
@ -31,11 +45,20 @@ if test -n "$bootable"; then
fi fi
done done
bootFlags="-b $bootImage -c .boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table" isoBootFlags="-eltorito-boot ${bootImage}
-eltorito-catalog .boot.cat
-no-emul-boot -boot-load-size 4 -boot-info-table"
fi
if test -n "$usbBootable"; then
usbBootFlags="-isohybrid-mbr ${isohybridMbrImage}"
fi fi
if test -n "$efiBootable"; then if test -n "$efiBootable"; then
bootFlags="$bootFlags -eltorito-alt-boot -e $efiBootImage -no-emul-boot" efiBootFlags="-eltorito-alt-boot
-e $efiBootImage
-no-emul-boot
-isohybrid-gpt-basdat"
fi fi
touch pathlist touch pathlist
@ -44,14 +67,14 @@ touch pathlist
# Add the individual files. # Add the individual files.
for ((i = 0; i < ${#targets_[@]}; i++)); do for ((i = 0; i < ${#targets_[@]}; i++)); do
stripSlash "${targets_[$i]}" stripSlash "${targets_[$i]}"
echo "$res=${sources_[$i]}" >> pathlist addPath "$res" "${sources_[$i]}"
done done
# Add the closures of the top-level store objects. # Add the closures of the top-level store objects.
storePaths=$(perl $pathsFromGraph closure-*) storePaths=$(perl $pathsFromGraph closure-*)
for i in $storePaths; do for i in $storePaths; do
echo "${i:1}=$i" >> pathlist addPath "${i:1}" "$i"
done done
@ -59,7 +82,7 @@ done
# nix-store --load-db. # nix-store --load-db.
if [ -n "$object" ]; then if [ -n "$object" ]; then
printRegistration=1 perl $pathsFromGraph closure-* > nix-path-registration printRegistration=1 perl $pathsFromGraph closure-* > nix-path-registration
echo "nix-path-registration=nix-path-registration" >> pathlist addPath "nix-path-registration" "nix-path-registration"
fi fi
@ -70,22 +93,39 @@ for ((n = 0; n < ${#objects[*]}; n++)); do
if test "$symlink" != "none"; then if test "$symlink" != "none"; then
mkdir -p $(dirname ./$symlink) mkdir -p $(dirname ./$symlink)
ln -s $object ./$symlink ln -s $object ./$symlink
echo "$symlink=./$symlink" >> pathlist addPath "$symlink" "./$symlink"
fi fi
done done
# !!! what does this do?
cat pathlist | sed -e 's/=\(.*\)=\(.*\)=/\\=\1=\2\\=/' | tee pathlist.safer
mkdir -p $out/iso mkdir -p $out/iso
genCommand="genisoimage -iso-level 4 -r -J $bootFlags -hide-rr-moved -graft-points -path-list pathlist.safer ${volumeID:+-V $volumeID}"
if test -z "$compressImage"; then xorriso="xorriso
$genCommand -o $out/iso/$isoName -as mkisofs
else -iso-level 3
$genCommand | bzip2 > $out/iso/$isoName.bz2 -volid ${volumeID}
-appid nixos
-publisher nixos
-graft-points
-full-iso9660-filenames
${isoBootFlags}
${usbBootFlags}
${efiBootFlags}
-r
-path-list pathlist
--sort-weight 0 /
--sort-weight 1 /isolinux" # Make sure isolinux is near the beginning of the ISO
$xorriso -output $out/iso/$isoName
if test -n "$usbBootable"; then
echo "Making image hybrid..."
isohybrid --uefi $out/iso/$isoName
fi fi
if test -n "$compressImage"; then
echo "Compressing image..."
bzip2 $out/iso/$isoName
fi
mkdir -p $out/nix-support mkdir -p $out/nix-support
echo $system > $out/nix-support/system echo $system > $out/nix-support/system

Some files were not shown because too many files have changed in this diff Show More