From a34a198006dd1baebb8431652d8fcf3679ec3ad5 Mon Sep 17 00:00:00 2001 From: Wouter den Breejen Date: Sun, 13 Jan 2008 16:36:27 +0000 Subject: [PATCH] Merged the Nix sources from the trunk from R9751 to R10133 for my State Nix project. --- configure.ac | 6 +- doc/manual/build-farm.xml | 8 +- doc/manual/builtins.xml | 11 +- doc/manual/glossary.xml | 4 +- doc/manual/installation.xml | 17 +- doc/manual/introduction.xml | 2 +- doc/manual/nix-build.xml | 1 + doc/manual/nix-channel.xml | 10 +- doc/manual/nix-env.xml | 216 ++++++++++++++++-- doc/manual/nix-store.xml | 174 +++++++++++++++ doc/manual/opt-common.xml | 11 + doc/manual/opt-inst-syn.xml | 7 + doc/manual/package-management.xml | 60 ++--- doc/manual/quick-start.xml | 27 +-- doc/manual/release-notes.xml | 292 ++++++++++++++++++------- doc/manual/troubleshooting.xml | 44 +++- doc/manual/writing-nix-expressions.xml | 139 +++++++++--- install_full.sh | 2 +- mergeTrunkBackIn.sh | 3 +- misc/vim/syntax/nix.vim | 35 +++ scripts/nix-push.in | 4 +- src/bsdiff-4.3/bspatch.c | 1 + src/libexpr/lexer.l | 27 +++ src/libexpr/nixexpr-ast.def | 3 + src/libexpr/parser.y | 109 ++++++++- src/libexpr/primops.cc | 26 ++- src/libstore/build.cc | 38 ++++ src/libstore/gc.cc | 20 +- src/libstore/store-api.cc | 19 ++ src/libstore/store-api.hh | 10 + src/libutil/util.cc | 15 +- src/nix-env/help.txt | 3 +- src/nix-env/nix-env.cc | 44 ++-- src/nix-store/help.txt | 9 +- src/nix-store/nix-store.cc | 33 +-- tests/dummy | 1 - tests/hash.sh | 2 +- tests/init.sh | 14 ++ tests/lang/eval-okay-context.exp | 1 + tests/lang/eval-okay-context.nix | 6 + tests/lang/eval-okay-ind-string.exp | 1 + tests/lang/eval-okay-ind-string.nix | 113 ++++++++++ tests/lang/eval-okay-readfile.exp | 1 + tests/lang/eval-okay-readfile.nix | 1 + tests/simple.sh | 7 +- tests/user-envs.sh | 11 + 46 files changed, 1323 insertions(+), 265 deletions(-) create mode 100644 misc/vim/syntax/nix.vim delete mode 100644 tests/dummy create mode 100644 tests/lang/eval-okay-context.exp create mode 100644 tests/lang/eval-okay-context.nix create mode 100644 tests/lang/eval-okay-ind-string.exp create mode 100644 tests/lang/eval-okay-ind-string.nix create mode 100644 tests/lang/eval-okay-readfile.exp create mode 100644 tests/lang/eval-okay-readfile.nix diff --git a/configure.ac b/configure.ac index 7f2b0a7ce..221aa598f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(nix, 0.11) +AC_INIT(nix, 0.12) AC_CONFIG_SRCDIR(README) AC_CONFIG_AUX_DIR(config) AM_INIT_AUTOMAKE([dist-bzip2 foreign]) @@ -273,6 +273,10 @@ AM_CONDITIONAL(INIT_STATE, test "$init_state" = "yes") AC_CHECK_FUNCS([setresuid setreuid lchown]) +# Nice to have, but not essential. +AC_CHECK_FUNCS([strsignal]) + + # This is needed if ATerm, Berkeley DB or bzip2 are static libraries, # and the Nix libraries are dynamic. if test "$(uname)" = "Darwin"; then diff --git a/doc/manual/build-farm.xml b/doc/manual/build-farm.xml index cfca63f36..9a6345896 100644 --- a/doc/manual/build-farm.xml +++ b/doc/manual/build-farm.xml @@ -36,10 +36,10 @@ build farm, since: builds, and Nix expressions are self-contained. Nix will only rebuild things that have actually - changed. For instance, if the sources of a component haven't - changed between runs of the build farm, the component won't be - rebuild (unless it was garbage-collected). Also, dependencies - typically don't change very often, so they only need to be built + changed. For instance, if the sources of a package haven't changed + between runs of the build farm, the package won't be rebuilt (unless + it was garbage-collected). Also, dependencies typically don't + change very often, so they only need to be built once. The results of a Nix build farm can be made diff --git a/doc/manual/builtins.xml b/doc/manual/builtins.xml index b6c886199..3b6b80324 100644 --- a/doc/manual/builtins.xml +++ b/doc/manual/builtins.xml @@ -441,6 +441,15 @@ in config.someSetting --> + builtins.readFile + path + + Return the contents of the file + path as a string. + + + + removeAttrs attrs list @@ -477,7 +486,7 @@ removeAttrs { x = 1; y = 2; z = 3; } ["a" "x" "z"] - builtins.substr + builtins.substring start len s diff --git a/doc/manual/glossary.xml b/doc/manual/glossary.xml index e76f99a26..efbf96f0a 100644 --- a/doc/manual/glossary.xml +++ b/doc/manual/glossary.xml @@ -74,9 +74,9 @@ Nix expression - A high-level description of software components and + A high-level description of software packages and compositions thereof. Deploying software using Nix entails writing - Nix expressions for your components. Nix expressions are translated + Nix expressions for your packages. Nix expressions are translated to derivations that are stored in the Nix store. These derivations can then be built. diff --git a/doc/manual/installation.xml b/doc/manual/installation.xml index 72e4b541a..d61c0c230 100644 --- a/doc/manual/installation.xml +++ b/doc/manual/installation.xml @@ -42,9 +42,8 @@ platforms as well.
Obtaining Nix The easiest way to obtain Nix is to download a source -distribution. RPMs for Red Hat, SuSE, and Fedora Core are also -available. +xlink:href="http://nix.cs.uu.nl/">source distribution. RPMs +for Red Hat, SuSE, and Fedora Core are also available. Alternatively, the most recent sources of Nix can be obtained from its
Installing from RPMs -RPM packages of Nix can be downloaded from http://www.cs.uu.nl/groups/ST/Trace/Nix. -These RPMs should work for most fairly recent releases of SuSE and Red -Hat Linux. They have been known to work work on SuSE Linux 8.1 and -9.0, and Red Hat 9.0. In fact, it should work on any RPM-based Linux -distribution based on glibc 2.3 or later. +RPM packages of Nix can be downloaded from . These RPMs should work for most +fairly recent releases of SuSE and Red Hat Linux. They have been +known to work work on SuSE Linux 8.1 and 9.0, and Red Hat 9.0. In +fact, it should work on any RPM-based Linux distribution based on +glibc 2.3 or later. Once downloaded, the RPMs can be installed or upgraded using rpm -U. For example, diff --git a/doc/manual/introduction.xml b/doc/manual/introduction.xml index 7f7cd11d5..d2f23bf44 100644 --- a/doc/manual/introduction.xml +++ b/doc/manual/introduction.xml @@ -50,7 +50,7 @@ are complete. In general, when you’re making a package for a package management system like RPM, you have to specify for each package what its dependencies are, but there are no guarantees that this specification is complete. If you forget a dependency, then the -component will build and work correctly on your +package will build and work correctly on your machine if you have the dependency installed, but not on the end user's machine if it's not there. diff --git a/doc/manual/nix-build.xml b/doc/manual/nix-build.xml index 3f35f5de3..695ddcf46 100644 --- a/doc/manual/nix-build.xml +++ b/doc/manual/nix-build.xml @@ -19,6 +19,7 @@ nix-build name value + name value diff --git a/doc/manual/nix-channel.xml b/doc/manual/nix-channel.xml index 8ee4a5f27..14021067c 100644 --- a/doc/manual/nix-channel.xml +++ b/doc/manual/nix-channel.xml @@ -62,11 +62,11 @@ also . Downloads the Nix expressions of all subscribed - channels, makes the conjunction of these the default for - nix-env operations (by calling nix-env - -I), and performs a nix-pull on the - manifests of all channels to make pre-built binaries - available. + channels, makes them the default for nix-env + operations (by symlinking them in the directory + ~/.nix-defexpr), and performs a + nix-pull on the manifests of all channels to + make pre-built binaries available. diff --git a/doc/manual/nix-env.xml b/doc/manual/nix-env.xml index 9af8c0c02..9f73b2d4c 100644 --- a/doc/manual/nix-env.xml +++ b/doc/manual/nix-env.xml @@ -19,6 +19,7 @@ nix-env name value + name value @@ -48,7 +49,7 @@ Description The command nix-env is used to manipulate Nix -user environments. User environments are sets of software components +user environments. User environments are sets of software packages available to a user at some point in time. In other words, they are a synthesised view of the programs available in the Nix store. There may be many user environments: different users can have different @@ -141,13 +142,33 @@ linkend="sec-common-options" />. ~/.nix-defexpr - - - The default Nix expression used by the - , , and - operations to obtain - derivations. The option may be used to - override this default. + A directory that contains the default Nix + expressions used by the , + , and operations to obtain derivations. The + option may be used to override this + default. + + The Nix expressions in this directory are combined into a + single attribute set, with each file as an attribute that has the + name of the file. Thus, if ~/.nix-defexpr + contains two files, foo and + bar, then the default Nix expression will + essentially be + + +{ + foo = import ~/.nix-defexpr/foo; + bar = import ~/.nix-defexpr/bar; +} + + + + The command nix-channel places symlinks + to the downloaded Nix expressions from each subscribed channel in + this directory. + + @@ -212,11 +233,21 @@ number of possible ways: If there are multiple derivations matching a name in args that have the same name (e.g., gcc-3.3.6 and gcc-4.1.1), then - only the highest version will be installed. You can force the - installation of multiple derivations with the same name by being - specific about the versions. For instance, nix-env -i - gcc-3.3.6 gcc-4.1.1 will install both version of GCC (and - will probably cause a user environment conflict!). + the derivation with the highest priority is + used. A derivation can define a priority by declaring the + meta.priority attribute. This attribute should + be a number, with a higher value denoting a lower priority. The + default priority is 0. + + If there are multiple matching derivations with the same + priority, then the derivation with the highest version will be + installed. + + You can force the installation of multiple derivations with + the same name by being specific about the versions. For instance, + nix-env -i gcc-3.3.6 gcc-4.1.1 will install both + version of GCC (and will probably cause a user environment + conflict!). If @@ -263,6 +294,15 @@ number of possible ways: + / + + Use only derivations for which a substitute is + registered, i.e., there is a pre-built binary available that can + be downloaded in lieu of building the derivation. Thus, no + packages will be built from source. + + + @@ -378,7 +418,7 @@ the following paths will be substituted: -Operation <option>--upgrade</option> +Operation <option>--upgrade</option> Synopsis @@ -463,6 +503,9 @@ installed. +For the other flags, see . + Examples @@ -572,6 +615,111 @@ $ nix-env -e '*' (remove everything) + + +Operation <option>--set-flag</option> + +Synopsis + + + nix-env + + name + value + drvnames + + + +Description + +The operation allows meta attributes +of installed packages to be modified. There are several attributes +that can be usefully modified, because they affect the behaviour of +nix-env or the user environment build +script: + + + + priority can be changed to + resolve filename clashes. The user environment build script uses + the meta.priority attribute of derivations to + resolve filename collisions between packages. Lower priority values + denote a higher priority. For instance, the GCC wrapper package and + the Binutils package in Nixpkgs both have a file + bin/ld, so previously if you tried to install + both you would get a collision. Now, on the other hand, the GCC + wrapper declares a higher priority than Binutils, so the former’s + bin/ld is symlinked in the user + environment. + + keep can be set to + true to prevent the package from being upgraded + or replaced. This is useful if you want to hang on to an older + version of a package. + + active can be set to + false to “disable” the package. That is, no + symlinks will be generated to the files of the package, but it + remains part of the profile (so it won’t be garbage-collected). It + can be set back to true to re-enable the + package. + + + + + + + +Examples + +To prevent the currently installed Firefox from being upgraded: + + +$ nix-env --set-flag keep true firefox + +After this, nix-env -u will ignore Firefox. + +To disable the currently installed Firefox, then install a new +Firefox while the old remains part of the profile: + + +$ nix-env -q \* +firefox-2.0.0.9 (the current one) + +$ nix-env --preserve-installed -i firefox-2.0.0.11 +installing `firefox-2.0.0.11' +building path(s) `/nix/store/myy0y59q3ig70dgq37jqwg1j0rsapzsl-user-environment' +Collission between `/nix/store/...-firefox-2.0.0.11/bin/firefox' + and `/nix/store/...-firefox-2.0.0.9/bin/firefox'. +(i.e., can’t have two active at the same time) + +$ nix-env --set-flag active false firefox +setting flag on `firefox-2.0.0.9' + +$ nix-env --preserve-installed -i firefox-2.0.0.11 +installing `firefox-2.0.0.11' + +$ nix-env -q \* +firefox-2.0.0.11 (the enabled one) +firefox-2.0.0.9 (the disabled one) + + + +To make files from binutils take precedence +over files from gcc: + + +$ nix-env --set-flag priority 5 binutils +$ nix-env --set-flag priority 10 gcc + + + + + + + + + Operation <option>--query</option> @@ -598,7 +746,12 @@ $ nix-env -e '*' (remove everything) - + + + + + + @@ -621,6 +774,7 @@ $ nix-env -e '*' (remove everything) + @@ -707,6 +861,16 @@ user environment elements, etc. --> + / + + Show only derivations for which a substitute is + registered, i.e., there is a pre-built binary available that can + be downloaded in lieu of building the derivation. Thus, this + shows all packages that probably can be installed + quickly. + + + @@ -726,8 +890,8 @@ user environment elements, etc. --> - - + + Print the attribute path of the derivation, which can be used to unambiguously select it using @@ -750,35 +914,35 @@ user environment elements, etc. --> Compare installed versions to available versions, or vice versa (if is given). This is useful for quickly seeing whether upgrades for installed - components are available in a Nix expression. A column is added + packages are available in a Nix expression. A column is added with the following meaning: < version - A newer version of the component is available + A newer version of the package is available or installed. = version - At most the same version of the component is + At most the same version of the package is available or installed. > version - Only older versions of the component are + Only older versions of the package are available or installed. - ? - No version of the component is available or + No version of the package is available or installed. @@ -819,6 +983,14 @@ user environment elements, etc. --> + + + Print all of the meta-attributes of the + derivation. This option is only available with + . + + + diff --git a/doc/manual/nix-store.xml b/doc/manual/nix-store.xml index a168be024..da3eae2ec 100644 --- a/doc/manual/nix-store.xml +++ b/doc/manual/nix-store.xml @@ -779,4 +779,178 @@ archive is read from standard input. + + +Operation <option>--export</option> + + + Synopsis + + nix-store + + paths + + + +Description + +The operation writes a serialisation +of the specified store paths to standard output in a format that can +be imported into another Nix store with nix-store --import. This +is like nix-store +--dump, except that the NAR archive produced by that command +doesn’t contain the necessary meta-information to allow it to be +imported into another Nix store (namely, the set of references of the +path). + +This command does not produce a closure of +the specified paths, so if a store path references other store paths +that are missing in the target Nix store, the import will fail. To +copy a whole closure, do something like + + +$ nix-store --export $(nix-store -qR paths) > out + + + +For an example of how and + can be used, see the source of the nix-copy-closure +command. + + + + + + + + + +Operation <option>--import</option> + + + Synopsis + + nix-store + + + + +Description + +The operation reads a serialisation of +a set of store paths produced by nix-store --import from +standard input and adds those store paths to the Nix store. Paths +that already exist in the Nix store are ignored. If a path refers to +another path that doesn’t exist in the Nix store, the import +fails. + + + + + + + + + +Operation <option>--optimise</option> + + + Synopsis + + nix-store + + + + +Description + +The operation reduces Nix store disk +space usage by finding identical files in the store and hard-linking +them to each other. It typically reduces the size of the store by +something like 25-35%. Only regular files and symlinks are +hard-linked in this manner. Files are considered identical when they +have the same NAR archive serialisation: that is, regular files must +have the same contents and permission (executable or non-executable), +and symlinks must have the same contents. + +After completion, or when the command is interrupted, a report +on the achieved savings is printed on standard error. + +Use or to get some +progress indication. + + + +Example + + +$ nix-store --optimise +hashing files in `/nix/store/qhqx7l2f1kmwihc9bnxs7rc159hsxnf3-gcc-4.1.1' +... +541838819 bytes (516.74 MiB) freed by hard-linking 54143 files; +there are 114486 files with equal contents out of 215894 files in total + + + + + + + + + + +Operation <option>--read-log</option> + + + Synopsis + + nix-store + + + + + paths + + + +Description + +The operation prints the build log +of the specified store paths on standard output. The build log is +whatever the builder of a derivation wrote to standard output and +standard error. If a store path is not a derivation, the deriver of +the store path is used. + +Build logs are kept in +/nix/var/log/nix/drvs. However, there is no +guarantee that a build log is available for any particular store +path. For instance, if the path was downloaded as a pre-built binary +through a substitute, then the log is unavailable. + + + +Example + + +$ nix-store -l $(which ktorrent) +building /nix/store/dhc73pvzpnzxhdgpimsd9sw39di66ph1-ktorrent-2.2.1 +unpacking sources +unpacking source archive /nix/store/p8n1jpqs27mgkjw07pb5269717nzf5f8-ktorrent-2.2.1.tar.gz +ktorrent-2.2.1/ +ktorrent-2.2.1/NEWS +... + + + + + + + + + + + diff --git a/doc/manual/opt-common.xml b/doc/manual/opt-common.xml index 7dfb7b8f8..316ad6658 100644 --- a/doc/manual/opt-common.xml +++ b/doc/manual/opt-common.xml @@ -268,6 +268,17 @@ + name value + + This option is like , only the + value is not a Nix expression but a string. So instead of + --arg system \"i686-linux\" (the outer quotes are + to keep the shell happy) you can say --argstr system + i686-linux. + + + + / attrPath diff --git a/doc/manual/opt-inst-syn.xml b/doc/manual/opt-inst-syn.xml index 1c32325e5..e8c3f1ec6 100644 --- a/doc/manual/opt-inst-syn.xml +++ b/doc/manual/opt-inst-syn.xml @@ -1,5 +1,12 @@ + + + + + + + diff --git a/doc/manual/package-management.xml b/doc/manual/package-management.xml index a24ca0a69..9ab181692 100644 --- a/doc/manual/package-management.xml +++ b/doc/manual/package-management.xml @@ -6,9 +6,9 @@ This chapter discusses how to do package management with Nix, -i.e., how to obtain, install, upgrade, and erase components. This is +i.e., how to obtain, install, upgrade, and erase packages. This is the “user’s” perspective of the Nix system — people -who want to create components should consult +who want to create packages should consult . @@ -16,8 +16,8 @@ who want to create components should consult The main command for package management is nix-env. You can use -it to install, upgrade, and erase components, and to query what -components are installed or are available for installation. +it to install, upgrade, and erase packages, and to query what +packages are installed or are available for installation. In Nix, different users can have different “views” on the set of installed applications. That is, there might be lots of @@ -30,10 +30,10 @@ environment, which is just a directory tree consisting of symlinks to the files of the active applications. Components are installed from a set of Nix -expressions that tell Nix how to build those components, +expressions that tell Nix how to build those packages, including, if necessary, their dependencies. There is a collection of Nix expressions called the Nix Package collection that contains -components ranging from basic development stuff such as GCC and Glibc, +packages ranging from basic development stuff such as GCC and Glibc, to end-user applications like Mozilla Firefox. (Nix is however not tied to the Nix Package collection; you could write your own Nix expressions based on it, or completely new ones.) You can download @@ -41,7 +41,7 @@ the latest version from . Assuming that you have downloaded and unpacked a release of Nix -Packages, you can view the set of available components in the release: +Packages, you can view the set of available packages in the release: $ nix-env -qaf nixpkgs-version '*' @@ -74,7 +74,7 @@ gcc-4.1.1 It is also possible to see the status of -available components, i.e., whether they are installed into the user +available packages, i.e., whether they are installed into the user environment and/or present in the system: @@ -86,24 +86,24 @@ IPS bison-1.875d ... The first character (I) indicates whether the -component is installed in your current user environment. The second +package is installed in your current user environment. The second (P) indicates whether it is present on your system (in which case installing it into your user environment would be a very quick operation). The last one (S) indicates whether there is a so-called substitute for the -component, which is Nix’s mechanism for doing binary deployment. It -just means that Nix knows that it can fetch a pre-built component from +package, which is Nix’s mechanism for doing binary deployment. It +just means that Nix knows that it can fetch a pre-built package from somewhere (typically a network server) instead of building it locally. So now that we have a set of Nix expressions we can build the -components contained in them. This is done using nix-env +packages contained in them. This is done using nix-env -i. For instance, $ nix-env -f nixpkgs-version -i subversion -will install the component called subversion (which +will install the package called subversion (which is, of course, the Subversion version management system). @@ -112,7 +112,7 @@ management system). Subversion and all its dependencies. This will take quite a while — typically an hour or two on modern machines. Fortunately, there is a faster way (so do a Ctrl-C on that install operation!): you just need -to tell Nix that pre-built binaries of all those components are +to tell Nix that pre-built binaries of all those packages are available somewhere. This is done using the nix-pull command, which must be supplied with a URL containing a manifest describing what binaries @@ -153,7 +153,7 @@ expressions, use -i instead of -u; -i will remove whatever version is already installed. -You can also upgrade all components for which there are newer +You can also upgrade all packages for which there are newer versions: @@ -199,19 +199,19 @@ set. implementing the ability to allow different users to have different configurations, and to do atomic upgrades and rollbacks. To understand how they work, it’s useful to know a bit about how Nix -works. In Nix, components are stored in unique locations in the +works. In Nix, packages are stored in unique locations in the Nix store (typically, /nix/store). For instance, a particular version -of the Subversion component might be stored in a directory +of the Subversion package might be stored in a directory /nix/store/dpmvp969yhdqs7lm2r1a3gng7pyq6vy4-subversion-1.1.3/, while another version might be stored in /nix/store/5mq2jcn36ldlmh93yj1n8s9c95pj7c5s-subversion-1.1.2. The long strings prefixed to the directory names are cryptographic hashes160-bit truncations of SHA-256 hashes encoded in a base-32 notation, to be precise. of -all inputs involved in building the component — +all inputs involved in building the package — sources, dependencies, compiler flags, and so on. So if two -components differ in any way, they end up in different locations in +packages differ in any way, they end up in different locations in the file system, so they don’t interfere with each other. shows a part of a typical Nix store. @@ -231,12 +231,12 @@ $ /nix/store/dpmvp969yhdq...-subversion-1.1.3/bin/svn every time you want to run Subversion. Of course we could set up the PATH environment variable to include the -bin directory of every component we want to use, +bin directory of every package we want to use, but this is not very convenient since changing PATH doesn’t take effect for already existing processes. The solution Nix uses is to create directory trees of symlinks to -activated components. These are called -user environments and they are components +activated packages. These are called +user environments and they are packages themselves (though automatically generated by nix-env), so they too reside in the Nix store. For instance, in the user @@ -285,8 +285,8 @@ operation, a new user environment and generation link are created based on the current one, and finally the default symlink is made to point at the new generation. This last step is atomic on Unix, which explains how we can do atomic upgrades. (Note -that the building/installing of new components doesn’t interfere in -any way with old components, since they are stored in different +that the building/installing of new packages doesn’t interfere in +any way with old packages, since they are stored in different locations in the Nix store.) If you find that you want to undo a nix-env @@ -352,18 +352,18 @@ This will not change the nix-env operations such as upgrades () and uninstall () never -actually delete components from the system. All they do (as shown +actually delete packages from the system. All they do (as shown above) is to create a new user environment that no longer contains -symlinks to the “deleted” components. +symlinks to the “deleted” packages. -Of course, since disk space is not infinite, unused components +Of course, since disk space is not infinite, unused packages should be removed at some point. You can do this by running the Nix -garbage collector. It will remove from the Nix store any component +garbage collector. It will remove from the Nix store any package not used (directly or indirectly) by any generation of any profile. Note however that as long as old generations reference a -component, it will not be deleted. After all, we wouldn’t be able to +package, it will not be deleted. After all, we wouldn’t be able to do a rollback otherwise. So in order for garbage collection to be effective, you should also delete (some) old generations. Of course, this should only be done if you are certain that you will not need to @@ -486,7 +486,7 @@ makes the union of each channel’s Nix expressions the default for $ nix-env -u '*' -to upgrade all components in your profile to the latest versions +to upgrade all packages in your profile to the latest versions available in the subscribed channels.
diff --git a/doc/manual/quick-start.xml b/doc/manual/quick-start.xml index c4065ace1..b51f2b167 100644 --- a/doc/manual/quick-start.xml +++ b/doc/manual/quick-start.xml @@ -11,7 +11,7 @@ to the following chapters.
Download a source tarball or RPM from . Build source +xlink:href='http://nix.cs.uu.nl/'/>. Build source distributions using the regular sequence: @@ -22,8 +22,9 @@ $ make install (as root) This will install Nix in /nix. You shouldn't change the prefix if at all possible since that will make it -impossible to use our pre-built components. Alternatively, you could -grab an RPM if you're on an RPM-based system. You should also add +impossible to use pre-built binaries from the Nixpkgs channel and +other channels. Alternatively, you could grab an RPM if you're on an +RPM-based system. You should also add /nix/etc/profile.d/nix.sh to your ~/.bashrc (or some other login file). @@ -40,14 +41,14 @@ $ nix-channel --add \ $ nix-channel --update -Note that this in itself doesn't download any components, it just +Note that this in itself doesn't download any packages, it just downloads the Nix expressions that build them and stores them somewhere (under ~/.nix-defexpr, in case you're curious). Also, it registers the fact that pre-built binaries are available remotely. -See what installable components are currently -available in the channel: +See what installable packages are currently available +in the channel: $ nix-env -qa ’*’ (mind the quotes!) @@ -59,13 +60,13 @@ libxslt-1.1.0 -Install some components from the channel: +Install some packages from the channel: $ nix-env -i hello firefox ... -This should download the pre-built components; it should not build -them locally (if it does, something went wrong). +This should download pre-built packages; it should not build them +locally (if it does, something went wrong). Test that they work: @@ -92,8 +93,8 @@ $ nix-env -e hello $ nix-channel --update $ nix-env -u '*' -The latter command will upgrade each installed component for which -there is a “newer” version (as determined by comparing the version +The latter command will upgrade each installed package for which there +is a “newer” version (as determined by comparing the version numbers). You can also install specific packages directly from @@ -107,7 +108,7 @@ appear asking you whether it’s okay to install the package. Say installed. If you're unhappy with the result of a -nix-env action (e.g., an upgraded component turned +nix-env action (e.g., an upgraded package turned out not to work properly), you can go back: @@ -124,7 +125,7 @@ $ nix-collect-garbage -d diff --git a/doc/manual/release-notes.xml b/doc/manual/release-notes.xml index 727a3e4a6..656a28fca 100644 --- a/doc/manual/release-notes.xml +++ b/doc/manual/release-notes.xml @@ -8,36 +8,222 @@ -
Release 0.11 (TBA) +
Release 0.11 (December 31, +2007) + +Nix 0.11 has many improvements over the previous stable release. +The most important improvement is secure multi-user support. It also +features many usability enhancements and language extensions, many of +them prompted by NixOS, the purely functional Linux distribution based +on Nix. Here is an (incomplete) list: + - TODO: multi-user support. The old setuid method for - sharing a store between multiple users has been - removed. + Secure multi-user support. A single Nix store can + now be shared between multiple (possible untrusted) users. This is + an important feature for NixOS, where it allows non-root users to + install software. The old setuid method for sharing a store between + multiple users has been removed. Details for setting up a + multi-user store can be found in the manual. The new command nix-copy-closure gives you an easy and efficient way to exchange software between machines. It copies the missing parts of the closure of a set of - store path to or from a remote machine. + store path to or from a remote machine via + ssh. - nix-prefetch-url now by default - computes the SHA-256 hash of the file instead of the MD5 hash. In - calls to fetchurl you should pass an - sha256 attribute instead of - md5. You can pass either a hexadecimal or a - base-32 encoding of the hash. + A new kind of string literal: strings between double + single-quotes ('') have indentation + “intelligently” removed. This allows large strings (such as shell + scripts or configuration file fragments in NixOS) to cleanly follow + the indentation of the surrounding expression. It also requires + much less escaping, since '' is less common in + most languages than ". + + + nix-env + modifies the current generation of a profile so that it contains + exactly the specified derivation, and nothing else. For example, + nix-env -p /nix/var/nix/profiles/browser --set + firefox lets the profile named + browser contain just Firefox. + + + nix-env now maintains + meta-information about installed packages in profiles. The + meta-information is the contents of the meta + attribute of derivations, such as description or + homepage. The command nix-env -q --xml + --meta shows all meta-information. + nix-env now uses the + meta.priority attribute of derivations to resolve + filename collisions between packages. Lower priority values denote + a higher priority. For instance, the GCC wrapper package and the + Binutils package in Nixpkgs both have a file + bin/ld, so previously if you tried to install + both you would get a collision. Now, on the other hand, the GCC + wrapper declares a higher priority than Binutils, so the former’s + bin/ld is symlinked in the user + environment. + + + nix-env -i / -u: instead of + breaking package ties by version, break them by priority and version + number. That is, if there are multiple packages with the same name, + then pick the package with the highest priority, and only use the + version if there are multiple packages with the same + priority. + + This makes it possible to mark specific versions/variant in + Nixpkgs more or less desirable than others. A typical example would + be a beta version of some package (e.g., + gcc-4.2.0rc1) which should not be installed even + though it is the highest version, except when it is explicitly + selected (e.g., nix-env -i + gcc-4.2.0rc1). + + + nix-env --set-flag allows meta + attributes of installed packages to be modified. There are several + attributes that can be usefully modified, because they affect the + behaviour of nix-env or the user environment + build script: + + + + meta.priority can be changed + to resolve filename clashes (see above). + + meta.keep can be set to + true to prevent the package from being + upgraded or replaced. Useful if you want to hang on to an older + version of a package. + + meta.active can be set to + false to “disable” the package. That is, no + symlinks will be generated to the files of the package, but it + remains part of the profile (so it won’t be garbage-collected). + Set it back to true to re-enable the + package. + + + + + + + nix-env -q now has a flag + () that causes + nix-env to show only those derivations whose + output is already in the Nix store or that can be substituted (i.e., + downloaded from somewhere). In other words, it shows the packages + that can be installed “quickly”, i.e., don’t need to be built from + source. The flag is also available in + nix-env -i and nix-env -u to + filter out derivations for which no pre-built binary is + available. + + + The new option (in + nix-env, nix-instantiate and + nix-build) is like , except + that the value is a string. For example, --argstr system + i686-linux is equivalent to --arg system + \"i686-linux\" (note that + prevents annoying quoting around shell arguments). + + nix-store has a new operation () paths that shows the build log of the given paths. + + + + Nix now uses Berkeley DB 4.5. The database is + upgraded automatically, but you should be careful not to use old + versions of Nix that still use Berkeley DB 4.4. + + + + + + The option + (corresponding to the configuration setting + build-max-silent-time) allows you to set a + timeout on builds — if a build produces no output on + stdout or stderr for the given + number of seconds, it is terminated. This is useful for recovering + automatically from builds that are stuck in an infinite + loop. + + + nix-channel: each subscribed + channel is its own attribute in the top-level expression generated + for the channel. This allows disambiguation (e.g. nix-env + -i -A nixpkgs_unstable.firefox). + + + The substitutes table has been removed from the + database. This makes operations such as nix-pull + and nix-channel --update much, much + faster. + + + nix-pull now supports + bzip2-compressed manifests. This speeds up + channels. + + + nix-prefetch-url now has a + limited form of caching. This is used by + nix-channel to prevent unnecessary downloads when + the channel hasn’t changed. + + + nix-prefetch-url now by default + computes the SHA-256 hash of the file instead of the MD5 hash. In + calls to fetchurl you should pass the + sha256 attribute instead of + md5. You can pass either a hexadecimal or a + base-32 encoding of the hash. + + + Nix can now perform builds in an automatically + generated “chroot”. This prevents a builder from accessing stuff + outside of the Nix store, and thus helps ensure purity. This is an + experimental feature. + + + The new command nix-store + --optimise reduces Nix store disk space usage by finding + identical files in the store and hard-linking them to each other. + It typically reduces the size of the store by something like + 25-35%. + + + ~/.nix-defexpr can now be a + directory, in which case the Nix expressions in that directory are + combined into an attribute set, with the file names used as the + names of the attributes. The command nix-env + --import (which set the + ~/.nix-defexpr symlink) is + removed. + + Derivations can specify the new special attribute allowedReferences to enforce that the references in the output of a derivation are a subset of a declared set of @@ -47,17 +233,6 @@ for booting Linux don’t have any dependencies. - TODO: semantic cleanups of string concatenation - etc. (mostly in r6740). - - - TODO: now using Berkeley DB 4.5. - - - TODO: option in - nix-store --register-validity. - - The new attribute exportReferencesGraph allows builders access to the references graph of their inputs. This is used in NixOS for @@ -65,72 +240,27 @@ populated with the closure of certain paths. - TODO: option , - configuration setting - build-max-silent-time. + Fixed-output derivations (like + fetchurl) can define the attribute + impureEnvVars to allow external environment + variables to be passed to builders. This is used in Nixpkgs to + support proxy configuration, among other things. - TODO: nix-env - . - - - TODO: . - - - TODO: nix-env now maintains meta - info about installed packages in user environments. to show all meta info. - - - TODO: nix-env - . Specific flags: - active, priority, - keep. - - - TODO: nix-env - / take package priorities into - account. - - - nix-env -q now has a flag - () that causes - nix-env to show only those derivations whose - output is already in the Nix store or that can be substituted (i.e., - downloaded from somewhere). In other words, it shows the packages - that can be installed “quickly”, i.e., don’t need to be built from - source. TODO: flag is also available in nix-env -i / - -u. - - - TODO: new built-ins + Several new built-in functions: builtins.attrNames, builtins.filterSource, - builtins.sub, + builtins.isAttrs, + builtins.isFunction, + builtins.listToAttrs, builtins.stringLength, - builtins.substring. + builtins.sub, + builtins.substring, + throw, + builtins.trace, + builtins.readFile. - TODO: each subscribed channel is its own attribute - in the top-level expression generated for the channel, this allows - disambiguation (nix-env -qaA). - - - The substitutes table has been removed from the - database. This makes operations such as nix-pull - and nix-channel --update - much faster. - - - nix-prefetch-url now has a - limited form of caching. This is used by - nix-channel to prevent unnecessary downloads when - the channel hasn’t changed. - - - TODO: chroot support. - -
diff --git a/doc/manual/troubleshooting.xml b/doc/manual/troubleshooting.xml index e1e6c08c8..ddff0f297 100644 --- a/doc/manual/troubleshooting.xml +++ b/doc/manual/troubleshooting.xml @@ -4,7 +4,9 @@ Troubleshooting -This section provides solutions for some common problems. +This section provides solutions for some common problems. See +the Nix +bug tracker for a list of currently known issues.
Berkeley DB: <quote>Cannot allocate memory</quote> @@ -77,6 +79,46 @@ $ nix-store --verify
+
Berkeley DB out of locks + +It is possible, especially in nix-store +--verify or when running the garbage collector, to run out +of Berkeley DB locks, like this: + + +$ nix-store --verify +checking path existence +checking path realisability +checking the derivers table +checking the references table +Berkeley DB error: Lock table is out of available object entries +error: Db::get: Cannot allocate memory + + + +A workaround is to increase the number of locks that Berkeley DB +allocates. (The real solution would be for Nix to not use so many +locks.) This can be done by putting the following in the file +/nix/var/nix/db/DB_CONFIG: + + +set_lk_max_locks 100000 +set_lk_max_lockers 100000 +set_lk_max_objects 100000 + + +(Increase these numbers if necessary.) Then make sure that there are +no running Nix processes and delete the Berkeley DB environment: + + +$ rm /nix/var/nix/db/__db.* + +The Berkeley DB environment is automatically recreated with the new +limits when you run any Nix command. + +
+
Collisions in <command>nix-env</command> diff --git a/doc/manual/writing-nix-expressions.xml b/doc/manual/writing-nix-expressions.xml index 5fa9e423d..840eb120d 100644 --- a/doc/manual/writing-nix-expressions.xml +++ b/doc/manual/writing-nix-expressions.xml @@ -7,7 +7,7 @@ This chapter shows you how to write Nix expressions, which are -the things that tell Nix how to build components. It starts with a +the things that tell Nix how to build packages. It starts with a simple example (a Nix expression for GNU Hello), and then moves on to a more in-depth look at the Nix expression language. @@ -19,29 +19,28 @@ xlink:href='http://www.gnu.org/software/hello/hello.html'>GNU Hello package to the Nix Packages collection. Hello is a program that prints out the text Hello, world!. -To add a component to the Nix Packages collection, you generally +To add a package to the Nix Packages collection, you generally need to do three things: - Write a Nix expression for the component. This is a - file that describes all the inputs involved in building the - component, such as dependencies (other components required by the - component), sources, and so on. + Write a Nix expression for the package. This is a + file that describes all the inputs involved in building the package, + such as dependencies, sources, and so on. Write a builder. This is a shell scriptIn fact, it can be written in any language, but typically it's a bash shell - script. that actually builds the component from + script. that actually builds the package from the inputs. - Add the component to the file + Add the package to the file pkgs/top-level/all-packages.nix. The Nix expression written in the first step is a - function; it requires other components in order + function; it requires other packages in order to build it. In this step you put it all together, i.e., you call the function with the right arguments to build the actual - component. + package. @@ -83,8 +82,8 @@ the single Nix expression in that directory arguments: stdenv, fetchurl, and perl. They are needed to build Hello, but we don't know how to build them here; that's why they are function - arguments. stdenv is a component that is used - by almost all Nix Packages components; it provides a + arguments. stdenv is a package that is used + by almost all Nix Packages packages; it provides a standard environment consisting of the things you would expect in a basic Unix environment: a C/C++ compiler (GCC, to be precise), the Bash shell, fundamental Unix tools such as @@ -99,19 +98,19 @@ the single Nix expression in that directory e is the body of the function. So here, the entire remainder of the file is the body of the function; when given the required arguments, the body should - describe how to build an instance of the Hello component. + describe how to build an instance of the Hello package. - So we have to build a component. Building something from + So we have to build a package. Building something from other stuff is called a derivation in Nix (as opposed to sources, which are built by humans instead of computers). We perform a derivation by calling stdenv.mkDerivation. mkDerivation is a function provided by - stdenv that builds a component from a set of + stdenv that builds a package from a set of attributes. An attribute set is just a list of key/value pairs where each value is an arbitrary Nix expression. They take the general form @@ -125,10 +124,10 @@ the single Nix expression in that directory The attribute name specifies the symbolic - name and version of the component. Nix doesn't really care about + name and version of the package. Nix doesn't really care about these things, but they are used by for instance nix-env -q to show a human-readable name for - components. This attribute is required by + packages. This attribute is required by mkDerivation. @@ -149,7 +148,7 @@ the single Nix expression in that directory - The builder has to know what the sources of the component + The builder has to know what the sources of the package are. Here, the attribute src is bound to the result of a call to the fetchurl function. Given a URL and an MD5 hash of the expected contents of the file @@ -246,7 +245,7 @@ steps: Since Hello needs Perl, we have to make sure that Perl is in the PATH. The perl environment - variable points to the location of the Perl component (since it + variable points to the location of the Perl package (since it was passed in as an attribute to the derivation), so $perl/bin is the directory containing the Perl interpreter. @@ -276,7 +275,7 @@ steps: GNU Hello is a typical Autoconf-based package, so we first have to run its configure script. In Nix - every component is stored in a separate location in the Nix store, + every package is stored in a separate location in the Nix store, for instance /nix/store/9a54ba97fb71b65fda531012d0443ce2-hello-2.1.1. Nix computes this path by cryptographically hashing all attributes @@ -338,7 +337,7 @@ rec { function; it is missing some arguments that have to be filled in somewhere. In the Nix Packages collection this is done in the file pkgs/top-level/all-packages.nix, where all -Nix expressions for components are imported and called with the +Nix expressions for packages are imported and called with the appropriate arguments. shows some fragments of all-packages.nix. @@ -352,7 +351,7 @@ some fragments of mutually recursive set of attributes. That is, the attributes can refer to each other. This is precisely what we want since we want to plug the - various components into each other. + various packages into each other. @@ -522,8 +521,8 @@ genericBuild The buildInputs variable tells - setup to use the indicated components as - inputs. This means that if a component provides a + setup to use the indicated packages as + inputs. This means that if a package provides a bin subdirectory, it's added to PATH; if it has a include subdirectory, it's added to GCC's header search path; and so @@ -594,9 +593,9 @@ Laziness means that arguments to functions are evaluated only when they are needed. Functional means that functions are normal values that can be passed around and manipulated in interesting ways. The language is not a full-featured, general -purpose language. It's main job is to describe components, -compositions of components, and the variability within -components. +purpose language. It's main job is to describe packages, +compositions of packages, and the variability within +packages. This section presents the various features of the language. @@ -613,7 +612,10 @@ language. - Strings are enclosed between double + Strings can be written in three + ways. + + The most common way is to enclose the string between double quotes, e.g., "foo bar". Strings can span multiple lines. The special characters " and \ and the character sequence @@ -659,8 +661,73 @@ configureFlags = " some of which in turn contain expressions (e.g., ${mesa}). - As a convenience, URIs as defined in - appendix B of The second way to write string literals is as an + indented string, which is enclosed between + pairs of double single-quotes, like so: + + +'' + This is the first line. + This is the second line. + This is the third line. +'' + + This kind of string literal intelligently strips indentation from + the start of each line. To be precise, it strips from each line a + number of spaces equal to the minimal indentation of the string as + a whole (disregarding the indentation of empty lines). For + instance, the first and second line are indented two space, while + the third line is indented three spaces. Thus, two spaces are + stripped from each line, so the resulting string is + + +"This is the first line.\nThis is the second line.\n This is the third line.\n" + + + + Note that the whitespace and newline following the opening + '' is ignored if there is no non-whitespace + text on the initial line. + + Antiquotation + (${expr}}) is + supported in indented strings. + + Since ${ and '' have + special meaning in indented strings, you need a way to quote them. + ${ can be escaped by prefixing it with + '', i.e., ''${. + '' can be escaped by prefixing it with + ', i.e., '''. Finally, + linefeed, carriage-return and tab characters can be writted as + ''\n, ''\r, + ''\t. + + Indented strings are primarily useful in that they allow + multi-line string literals to follow the indentation of the + enclosing Nix expression, and that less escaping is typically + necessary for strings representing languages such as shell scripts + and configuration files because '' is much less + common than ". Example: + + +stdenv.mkDerivation { + ... + postInstall = + '' + mkdir $out/bin $out/etc + cp foo $out/bin + echo "Hello World" > $out/etc/foo.conf + ${if enableBar then "cp bar $out/bin" else ""} + ''; + ... +} + + + + + Finally, as a convenience, URIs as + defined in appendix B of RFC 2396 can be written as is, without quotes. For instance, the string @@ -1191,7 +1258,7 @@ set, the attributes of which specify the inputs of the build. There must be an attribute named name whose value must be a string. This is used - as a symbolic name for the component by nix-env, + as a symbolic name for the package by nix-env, and it is appended to the hash in the output path of the derivation. @@ -1579,7 +1646,7 @@ impureEnvVars = ["http_proxy" "https_proxy" ...]; The standard build environment in the Nix Packages collection provides a basic environment for building Unix packages. It consists -of the following components: +of the following packages: @@ -1645,13 +1712,13 @@ following: - All input components specified in the + All input packages specified in the buildInputs environment variable have their /bin subdirectory added to PATH, their /include subdirectory added to the C/C++ header file search path, and their /lib subdirectory added to the linker search path. This can be extended. - For instance, when the pkgconfig component is + For instance, when the pkgconfig package is used, the subdirectory /lib/pkgconfig of each input is added to the PKG_CONFIG_PATH environment variable. @@ -1668,8 +1735,8 @@ following: The setup script also exports a function called genericBuild that knows how to build -typical Autoconf-style components. It can be customised to perform -builds for any type of component. It is advisable to use +typical Autoconf-style packages. It can be customised to perform +builds for any type of package. It is advisable to use genericBuild since it provides facilities that are almost always useful such as unpacking of sources, patching of sources, nested logging, etc. diff --git a/install_full.sh b/install_full.sh index f180111a8..aa1cfba14 100755 --- a/install_full.sh +++ b/install_full.sh @@ -1,6 +1,6 @@ #! /bin/sh -e -make clean +make clean # comment this out when needed !!! export nixstatepath=/nixstate2/nix export ACLOCAL_PATH=/home/wouterdb/.nix-profile/share/aclocal diff --git a/mergeTrunkBackIn.sh b/mergeTrunkBackIn.sh index 9b400ea7d..95c8c6e19 100755 --- a/mergeTrunkBackIn.sh +++ b/mergeTrunkBackIn.sh @@ -1,4 +1,4 @@ -svn merge -r 9584:9751 https://svn.cs.uu.nl:12443/repos/trace/nix/trunk +svn merge -r 9751:10133 https://svn.cs.uu.nl:12443/repos/trace/nix/trunk #already done: # 8628 @@ -28,3 +28,4 @@ svn merge -r 9584:9751 https://svn.cs.uu.nl:12443/repos/trace/nix/trunk # 9561 # 9584 # 9751 +# 10133 TODO diff --git a/misc/vim/syntax/nix.vim b/misc/vim/syntax/nix.vim new file mode 100644 index 000000000..6e47a2171 --- /dev/null +++ b/misc/vim/syntax/nix.vim @@ -0,0 +1,35 @@ +" Vim syntax file +" Language: nix +" Maintainer: Marc Weber +" Modify and commit if you feel that way +" Last Change: 2007 Dec + +" Quit when a (custom) syntax file was already loaded +if exists("b:current_syntax") + finish +endif + +syn keyword nixKeyword let throw inherit import true false null with +syn keyword nixConditional if else then +syn keyword nixBrace ( ) { } = +syn keyword nixBuiltin __currentSystem __currentTime __isFunction __getEnv __trace __toPath __pathExists + \ __readFile __toXML __toFile __filterSource __attrNames __getAttr __hasAttr __isAttrs __listToAttrs __isList + \ __head __tail __add __sub __lessThan __substring __stringLength + +syn match nixAttr "\w\+\ze\s*=" +syn match nixFuncArg "\zs\w\+\ze\s*:" +syn region nixStringParam start=+\${+ end=+}+ +syn region nixMultiLineComment start=+/\*+ skip=+\\"+ end=+\*/+ +syn match nixEndOfLineComment "#.*$" +syn region nixString start=+"+ skip=+\\"+ end=+"+ contains=nixStringParam + +hi def link nixKeyword Keyword +hi def link nixConditional Conditional +hi def link nixBrace Special +hi def link nixString String +hi def link nixBuiltin Special +hi def link nixStringParam Macro +hi def link nixMultiLineComment Comment +hi def link nixEndOfLineComment Comment +hi def link nixAttr Identifier +hi def link nixFuncArg Identifier diff --git a/scripts/nix-push.in b/scripts/nix-push.in index 6250f8b0a..137e3112b 100644 --- a/scripts/nix-push.in +++ b/scripts/nix-push.in @@ -116,9 +116,9 @@ print NIX "]"; close NIX; -# Instantiate store expressions from the Nix expression. +# Instantiate store derivations from the Nix expression. my @storeExprs; -print STDERR "instantiating store expressions...\n"; +print STDERR "instantiating store derivations...\n"; my $pid = open(READ, "$binDir/nix-instantiate $nixExpr|") or die "cannot run nix-instantiate"; while () { diff --git a/src/bsdiff-4.3/bspatch.c b/src/bsdiff-4.3/bspatch.c index 741d4de0e..f9d33ddd6 100644 --- a/src/bsdiff-4.3/bspatch.c +++ b/src/bsdiff-4.3/bspatch.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD: src/usr.bin/bsdiff/bspatch/bspatch.c,v 1.1 2005/08/06 01:59: #include #include #include +#include static off_t offtin(u_char *buf) { diff --git a/src/libexpr/lexer.l b/src/libexpr/lexer.l index 9f0f0b335..cf90f2939 100644 --- a/src/libexpr/lexer.l +++ b/src/libexpr/lexer.l @@ -4,6 +4,7 @@ %x STRING +%x IND_STRING %{ @@ -122,6 +123,26 @@ inherit { return INHERIT; } \" { BEGIN(INITIAL); return '"'; } . return yytext[0]; /* just in case: shouldn't be reached */ +\'\'(\ *\n)? { BEGIN(IND_STRING); return IND_STRING_OPEN; } +([^\$\']|\$[^\{\']|\'[^\'])+ { + yylval->t = makeIndStr(toATerm(yytext)); + return IND_STR; + } +\'\'\$ { + yylval->t = makeIndStr(toATerm("$")); + return IND_STR; + } +\'\'\' { + yylval->t = makeIndStr(toATerm("''")); + return IND_STR; + } +\'\'\\. { + yylval->t = unescapeStr(yytext + 2); + return IND_STR; + } +\$\{ { BEGIN(INITIAL); return DOLLAR_CURLY; } +\'\' { BEGIN(INITIAL); return IND_STRING_CLOSE; } +. return yytext[0]; /* just in case: shouldn't be reached */ {PATH} { yylval->t = toATerm(yytext); return PATH; /* !!! alloc */ } {URI} { yylval->t = toATerm(yytext); return URI; /* !!! alloc */ } @@ -148,4 +169,10 @@ void backToString(yyscan_t scanner) BEGIN(STRING); } +void backToIndString(yyscan_t scanner) +{ + struct yyguts_t * yyg = (struct yyguts_t *) scanner; + BEGIN(IND_STRING); +} + } diff --git a/src/libexpr/nixexpr-ast.def b/src/libexpr/nixexpr-ast.def index c7029e927..a06d34311 100644 --- a/src/libexpr/nixexpr-ast.def +++ b/src/libexpr/nixexpr-ast.def @@ -46,6 +46,9 @@ Int | int | Expr | Str | string ATermList | Expr | Str | string | Expr | ObsoleteStr +# Internal to the parser, doesn't occur in ASTs. +IndStr | string | Expr | + # A path is a reference to a file system object that is to be copied # to the Nix store when used as a derivation attribute. When it is # concatenated to a string (i.e., `str + path'), it is also copied and diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 82b24cd07..cd3ba88aa 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -68,9 +68,100 @@ static Expr fixAttrs(int recursive, ATermList as) } -void backToString(yyscan_t scanner); +static Expr stripIndentation(ATermList es) +{ + if (es == ATempty) return makeStr(""); + + /* Figure out the minimum indentation. Note that by design + whitespace-only final lines are not taken into account. (So + the " " in "\n ''" is ignored, but the " " in "\n foo''" is.) */ + bool atStartOfLine = true; /* = seen only whitespace in the current line */ + unsigned int minIndent = 1000000; + unsigned int curIndent = 0; + ATerm e; + for (ATermIterator i(es); i; ++i) { + if (!matchIndStr(*i, e)) { + /* Anti-quotations end the current start-of-line whitespace. */ + if (atStartOfLine) { + atStartOfLine = false; + if (curIndent < minIndent) minIndent = curIndent; + } + continue; + } + string s = aterm2String(e); + for (unsigned int j = 0; j < s.size(); ++j) { + if (atStartOfLine) { + if (s[j] == ' ') + curIndent++; + else if (s[j] == '\n') { + /* Empty line, doesn't influence minimum + indentation. */ + curIndent = 0; + } else { + atStartOfLine = false; + if (curIndent < minIndent) minIndent = curIndent; + } + } else if (s[j] == '\n') { + atStartOfLine = true; + curIndent = 0; + } + } + } + + /* Strip spaces from each line. */ + ATermList es2 = ATempty; + atStartOfLine = true; + unsigned int curDropped = 0; + unsigned int n = ATgetLength(es); + for (ATermIterator i(es); i; ++i, --n) { + if (!matchIndStr(*i, e)) { + atStartOfLine = false; + curDropped = 0; + es2 = ATinsert(es2, *i); + continue; + } + + string s = aterm2String(e); + string s2; + for (unsigned int j = 0; j < s.size(); ++j) { + if (atStartOfLine) { + if (s[j] == ' ') { + if (curDropped++ >= minIndent) + s2 += s[j]; + } + else if (s[j] == '\n') { + curDropped = 0; + s2 += s[j]; + } else { + atStartOfLine = false; + curDropped = 0; + s2 += s[j]; + } + } else { + s2 += s[j]; + if (s[j] == '\n') atStartOfLine = true; + } + } + + /* Remove the last line if it is empty and consists only of + spaces. */ + if (n == 1) { + unsigned int p = s2.find_last_of('\n'); + if (p != string::npos && s2.find_first_not_of(' ', p + 1) == string::npos) + s2 = string(s2, 0, p + 1); + } + + es2 = ATinsert(es2, makeStr(s2)); + } + + return makeConcatStrings(ATreverse(es2)); +} + + +void backToString(yyscan_t scanner); +void backToIndString(yyscan_t scanner); + - static Pos makeCurPos(YYLTYPE * loc, ParseData * data) { return makePos(toATerm(data->path), @@ -121,10 +212,11 @@ static void freeAndUnprotect(void * p) %type start expr expr_function expr_if expr_op %type expr_app expr_select expr_simple bind inheritsrc formal -%type binds ids expr_list formals string_parts -%token ID INT STR PATH URI +%type binds ids expr_list formals string_parts ind_string_parts +%token ID INT STR IND_STR PATH URI %token IF THEN ELSE ASSERT WITH LET IN REC INHERIT EQ NEQ AND OR IMPL %token DOLLAR_CURLY /* == ${ */ +%token IND_STRING_OPEN IND_STRING_CLOSE %nonassoc IMPL %left OR @@ -199,6 +291,9 @@ expr_simple else if (ATgetNext($2) == ATempty) $$ = ATgetFirst($2); else $$ = makeConcatStrings(ATreverse($2)); } + | IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE { + $$ = stripIndentation(ATreverse($2)); + } | PATH { $$ = makePath(toATerm(absPath(aterm2String($1), data->basePath))); } | URI { $$ = makeStr($1, ATempty); } | '(' expr ')' { $$ = $2; } @@ -219,6 +314,12 @@ string_parts | { $$ = ATempty; } ; +ind_string_parts + : ind_string_parts IND_STR { $$ = ATinsert($1, $2); } + | ind_string_parts DOLLAR_CURLY expr '}' { backToIndString(scanner); $$ = ATinsert($1, $3); } + | { $$ = ATempty; } + ; + binds : binds bind { $$ = ATinsert($1, $2); } | { $$ = ATempty; } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index c082d3979..e0c4c070d 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -769,6 +769,17 @@ static Expr prim_dirOf(EvalState & state, const ATermVector & args) } +/* Return the contents of a file as a string. */ +static Expr prim_readFile(EvalState & state, const ATermVector & args) +{ + PathSet context; + Path path = coerceToPath(state, args[0], context); + if (!context.empty()) + throw EvalError(format("string `%1%' cannot refer to other paths") % path); + return makeStr(readFile(path)); +} + + /************************************************************* * Creating files *************************************************************/ @@ -1054,8 +1065,8 @@ static Expr prim_toString(EvalState & state, const ATermVector & args) } -/* `substr start len str' returns the substring of `str' starting at - character position `min(start, stringLength str)' inclusive and +/* `substring start len str' returns the substring of `str' starting + at character position `min(start, stringLength str)' inclusive and ending at `min(start + len, stringLength str)'. `start' must be non-negative. */ static Expr prim_substring(EvalState & state, const ATermVector & args) @@ -1079,6 +1090,14 @@ static Expr prim_stringLength(EvalState & state, const ATermVector & args) } +static Expr prim_unsafeDiscardStringContext(EvalState & state, const ATermVector & args) +{ + PathSet context; + string s = coerceToString(state, args[0], context); + return makeStr(s, PathSet()); +} + + /************************************************************* * Primop registration *************************************************************/ @@ -1116,6 +1135,7 @@ void EvalState::addPrimOps() addPrimOp("__pathExists", 1, prim_pathExists); addPrimOp("baseNameOf", 1, prim_baseNameOf); addPrimOp("dirOf", 1, prim_dirOf); + addPrimOp("__readFile", 1, prim_readFile); // Creating files addPrimOp("__toXML", 1, prim_toXML); @@ -1145,6 +1165,8 @@ void EvalState::addPrimOps() addPrimOp("toString", 1, prim_toString); addPrimOp("__substring", 3, prim_substring); addPrimOp("__stringLength", 1, prim_stringLength); + addPrimOp("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext); + } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 1b505d67b..913fba207 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -1671,6 +1671,44 @@ void DerivationGoal::startBuilder() makeValidityRegistration(refs, false)); } + // The same for derivations + s = drv.env["exportBuildReferencesGraph"]; + ss = tokenizeString(s); + if (ss.size() % 2 != 0) + throw BuildError(format("odd number of tokens in `exportReferencesGraph': `%1%'") % s); + for (Strings::iterator i = ss.begin(); i != ss.end(); ) { + string fileName = *i++; + checkStoreName(fileName); /* !!! abuse of this function */ + + /* Check that the store path is valid. */ + Path storePath = *i++; + if (!isInStore(storePath)) + throw BuildError(format("`exportReferencesGraph' contains a non-store path `%1%'") + % storePath); + storePath = toStorePath(storePath); + if (!store->isValidPath(storePath)) + throw BuildError(format("`exportReferencesGraph' contains an invalid path `%1%'") + % storePath); + + /* Write closure info to `fileName'. */ + PathSet refs1,refs; + computeFSClosure(storePath, refs1, true, false, 0); //TODO !!!!!!!!!!!!!!!!!!!!!!!!!!! WE (MAY) ALSO NEED TO COPY STATE + for (PathSet::iterator j = refs1.begin(); j != refs1.end() ; j++) { + refs.insert (*j); + if (isDerivation (*j)) { + Derivation deriv = derivationFromPath (*j); + for (DerivationOutputs::iterator k=deriv.outputs.begin(); + k != deriv.outputs.end(); k++) { + refs.insert(k->second.path); + } + } + } + /* !!! in secure Nix, the writing should be done on the + build uid for security (maybe). */ + writeStringToFile(tmpDir + "/" + fileName, + makeValidityRegistration(refs, false)); + } + /* If `build-users-group' is not empty, then we have to build as one of the members of that group. */ diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 0be0eda83..5d80b4b6e 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -26,7 +26,7 @@ static string gcLockName = "gc.lock"; static string tempRootsDir = "temproots"; static string gcRootsDir = "gcroots"; -const unsigned int defaultGcLevel = 1000; +static const int defaultGcLevel = 1000; /* Acquire the global GC lock. This is used to prevent new Nix @@ -450,7 +450,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete, queryBoolSetting("gc-keep-outputs", false); bool gcKeepDerivations = queryBoolSetting("gc-keep-derivations", true); - unsigned int gcKeepOutputsThreshold = + int gcKeepOutputsThreshold = queryIntSetting ("gc-keep-outputs-threshold", defaultGcLevel); //printMsg(lvlError, format("gcKeepOutputs %1% gcKeepDerivations: %2%") % gcKeepOutputs % gcKeepDerivations); @@ -536,7 +536,7 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete, else if (store->isValidStatePath(j->second.path)) computeFSClosure(j->second.path, livePaths, true, true, 0); ======= -*/ + string gcLevelStr = drv.env["__gcLevel"]; int gcLevel; @@ -550,6 +550,20 @@ void LocalStore::collectGarbage(GCAction action, const PathSet & pathsToDelete, if (store->isValidPath(j->second.path) || store->isValidStatePath(j->second.path)) computeFSClosure(j->second.path, livePaths, true, true, 0); } +======= +*/ + + string gcLevelStr = drv.env["__gcLevel"]; + int gcLevel; + if (!string2Int(gcLevelStr, gcLevel)) + gcLevel = defaultGcLevel; + + if (gcLevel >= gcKeepOutputsThreshold) + for (DerivationOutputs::iterator j = drv.outputs.begin(); + j != drv.outputs.end(); ++j) + if (store->isValidPath(j->second.path) || store->isValidStatePath(j->second.path)) + computeFSClosure(j->second.path, livePaths, true, true, 0); + } } if (action == gcReturnLive) { diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 1cc12907e..ab701a11b 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -92,6 +92,25 @@ Path toStoreOrStatePath(const Path & path) return Path(path, 0, slash); } +Path followLinksToStore(const Path & _path) +{ + Path path = absPath(_path); + while (!isInStore(path)) { + if (!isLink(path)) break; + string target = readLink(path); + path = absPath(target, dirOf(path)); + } + if (!isInStore(path)) + throw Error(format("path `%1%' is not in the Nix store") % path); + return path; +} + + +Path followLinksToStorePath(const Path & path) +{ + return toStorePath(followLinksToStore(path)); +} + void checkStoreName(const string & name) { diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 0998a22ab..75fce9558 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -259,11 +259,21 @@ bool isStatePath(const Path & path); void checkStoreName(const string & name); + /* Chop off the parts after the top-level store name, e.g., /nix/store/abcd-foo/bar => /nix/store/abcd-foo. */ Path toStorePath(const Path & path); Path toStoreOrStatePath(const Path & path); +/* Follow symlinks until we end up with a path in the Nix store. */ +Path followLinksToStore(const Path & path); + + +/* Same as followLinksToStore(), but apply toStorePath() to the + result. */ +Path followLinksToStorePath(const Path & path); + + /* Constructs a unique store path name. */ Path makeStorePath(const string & type, const Hash & hash, const string & suffix); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index c56e4229b..50a8cb3d3 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -106,8 +107,7 @@ Path canonPath(const Path & path, bool resolveSymlinks) /* If s points to a symlink, resolve it and restart (since the symlink target might contain new symlinks). */ if (resolveSymlinks && isLink(s)) { - followCount++; - if (followCount >= maxFollow) + if (++followCount >= maxFollow) throw Error(format("infinite symlink recursion in path `%1%'") % path); temp = absPath(readLink(s), dirOf(s)) + string(i, end); @@ -1031,8 +1031,15 @@ string statusToString(int status) if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { if (WIFEXITED(status)) return (format("failed with exit code %1%") % WEXITSTATUS(status)).str(); - else if (WIFSIGNALED(status)) - return (format("failed due to signal %1%") % WTERMSIG(status)).str(); + else if (WIFSIGNALED(status)) { + int sig = WTERMSIG(status); +#if HAVE_STRSIGNAL + const char * description = strsignal(sig); + return (format("failed due to signal %1% (%2%)") % sig % description).str(); +#else + return (format("failed due to signal %1%") % sig).str(); +#endif + } else return "died abnormally"; } else return "succeeded"; diff --git a/src/nix-env/help.txt b/src/nix-env/help.txt index e0697be88..605bf2810 100644 --- a/src/nix-env/help.txt +++ b/src/nix-env/help.txt @@ -9,6 +9,7 @@ Operations: --set: create a user environment containing a single derivation --uninstall / -e: remove derivations from the user environment --query / -q: perform a query on an environment or Nix expression + --set-flag NAME VALUE: set derivation meta-attribute to given value The previous operations take a list of derivation names. The special name `*' may be used to indicate all derivations. @@ -20,8 +21,6 @@ name `*' may be used to indicate all derivations. --delete-generations GENERATIONS...: deleted listed generations, `old' for all non-current generations - --import / -I FILE: set default Nix expression - --version: output version information --help: display help diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 7f2e606ab..b8e07df6b 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -430,7 +430,7 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, /* Check that all selectors have been used. */ for (DrvNames::iterator i = selectors.begin(); i != selectors.end(); ++i) - if (i->hits == 0) + if (i->hits == 0 && i->fullName != "*") throw Error(format("selector `%1%' matches no derivations") % i->fullName); @@ -438,13 +438,18 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, } +static bool isPath(const string & s) +{ + return s.find('/') != string::npos; +} + + static void queryInstSources(EvalState & state, const InstallSourceInfo & instSource, const Strings & args, DrvInfos & elems, bool newestOnly) { InstallSourceType type = instSource.type; - - if (type == srcUnknown && args.size() > 0 && args.front()[0] == '/') + if (type == srcUnknown && args.size() > 0 && isPath(args.front())) type = srcStorePaths; switch (type) { @@ -496,25 +501,24 @@ static void queryInstSources(EvalState & state, for (Strings::const_iterator i = args.begin(); i != args.end(); ++i) { - assertStorePath(*i); + Path path = followLinksToStorePath(*i); DrvInfo elem; elem.attrs = boost::shared_ptr(new ATermMap(0)); /* ugh... */ - string name = baseNameOf(*i); + string name = baseNameOf(path); string::size_type dash = name.find('-'); if (dash != string::npos) name = string(name, dash + 1); - if (isDerivation(*i)) { - elem.setDrvPath(*i); - elem.setOutPath(findOutput(derivationFromPath(*i), "out")); + if (isDerivation(path)) { + elem.setDrvPath(path); + elem.setOutPath(findOutput(derivationFromPath(path), "out")); if (name.size() >= drvExtension.size() && string(name, name.size() - drvExtension.size()) == drvExtension) name = string(name, 0, name.size() - drvExtension.size()); } - else - elem.setOutPath(*i); + else elem.setOutPath(path); elem.name = name; @@ -964,7 +968,7 @@ static void opSet(Globals & globals, } -static void uninstallDerivations(Globals & globals, DrvNames & selectors, +static void uninstallDerivations(Globals & globals, Strings & selectors, Path & profile) { PathLocks lock; @@ -977,11 +981,13 @@ static void uninstallDerivations(Globals & globals, DrvNames & selectors, { DrvName drvName(i->name); bool found = false; - for (DrvNames::iterator j = selectors.begin(); - j != selectors.end(); ++j) - if (j->matches(drvName)) { - printMsg(lvlInfo, - format("uninstalling `%1%'") % i->name); + for (Strings::iterator j = selectors.begin(); j != selectors.end(); ++j) + /* !!! the repeated calls to followLinksToStorePath() are + expensive, should pre-compute them. */ + if ((isPath(*j) && i->queryOutPath(globals.state) == followLinksToStorePath(*j)) + || DrvName(*j).matches(drvName)) + { + printMsg(lvlInfo, format("uninstalling `%1%'") % i->name); found = true; break; } @@ -1000,11 +1006,7 @@ static void opUninstall(Globals & globals, { if (opFlags.size() > 0) throw UsageError(format("unknown flag `%1%'") % opFlags.front()); - - DrvNames drvNames = drvNamesFromArgs(opArgs); - - uninstallDerivations(globals, drvNames, - globals.profile); + uninstallDerivations(globals, opArgs, globals.profile); } diff --git a/src/nix-store/help.txt b/src/nix-store/help.txt index a338fe7d1..40934966c 100644 --- a/src/nix-store/help.txt +++ b/src/nix-store/help.txt @@ -16,8 +16,13 @@ Operations: --gc: run the garbage collector - --dump: dump a path as a Nix archive - --restore: restore a path from a Nix archive + --dump: dump a path as a Nix archive, forgetting dependencies + --restore: restore a path from a Nix archive, without + registering validity + + --export: export a path as a Nix archive, marking dependencies + --import: import a path from a Nix archive, and register as + valid --init: initialise the Nix database --verify: verify Nix structures diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index d7d046d75..ce46796a6 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -29,7 +29,9 @@ static Path gcRoot; static int rootNr = 0; static bool indirectRoot = false; +/* //Fixes the path and checks if it is a store path , see also toStorePath +<<<<<<< .working static Path fixPath(Path path) { path = absPath(path); @@ -55,6 +57,9 @@ static Path fixStoreOrStatePath(Path path) return toStoreOrStatePath(path); } +======= +>>>>>>> .merge-right.r10133 +*/ static Path useDeriver(Path path) { @@ -99,7 +104,7 @@ static void opRealise(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) - *i = fixPath(*i); + *i = followLinksToStorePath(*i); if (opArgs.size() > 1) { PathSet drvPaths; @@ -292,7 +297,7 @@ static void opQuery(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { - *i = fixPath(*i); + *i = followLinksToStorePath(*i); if (forceRealise) realisePath(*i); Derivation drv = derivationFromPathTxn(noTxn, *i); cout << format("%1%\n") % findOutput(drv, "out"); @@ -313,8 +318,10 @@ static void opQuery(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { - Path path = maybeUseOutput(fixStoreOrStatePath(*i), useOutput, forceRealise); - if (query == qRequisites) store->storePathRequisites(path, includeOutputs, paths, true, false, revision); + Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise); + + if (query == qRequisites) + store->storePathRequisites(path, includeOutputs, paths, true, false, revision); else if (query == qRequisitesState) store->storePathRequisites(path, includeOutputs, paths, false, true, revision); else if (query == qRequisitesFull) store->storePathRequisites(path, includeOutputs, paths, true, true, revision); else if (query == qReferences) store->queryStoreReferences(path, paths, revision); @@ -335,7 +342,7 @@ static void opQuery(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { - Path deriver = store->queryDeriver(fixPath(*i)); + Path deriver = store->queryDeriver(followLinksToStorePath(*i)); cout << format("%1%\n") % (deriver == "" ? "unknown-deriver" : deriver); } @@ -345,7 +352,7 @@ static void opQuery(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { - Path path = useDeriver(fixPath(*i)); + Path path = useDeriver(followLinksToStorePath(*i)); Derivation drv = derivationFromPathTxn(noTxn, path); StringPairs::iterator j = drv.env.find(bindingName); if (j == drv.env.end()) @@ -359,7 +366,7 @@ static void opQuery(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { - Path path = maybeUseOutput(fixPath(*i), useOutput, forceRealise); + Path path = maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise); Hash hash = store->queryPathHash(path); assert(hash.type == htSHA256); cout << format("sha256:%1%\n") % printHash32(hash); @@ -370,7 +377,7 @@ static void opQuery(Strings opFlags, Strings opArgs) PathSet done; for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) - printTree(fixPath(*i), "", "", done); + printTree(followLinksToStorePath(*i), "", "", done); break; } @@ -378,7 +385,7 @@ static void opQuery(Strings opFlags, Strings opArgs) PathSet roots; for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) - roots.insert(maybeUseOutput(fixPath(*i), useOutput, forceRealise)); + roots.insert(maybeUseOutput(followLinksToStorePath(*i), useOutput, forceRealise)); printDotGraph(roots); break; } @@ -386,7 +393,7 @@ static void opQuery(Strings opFlags, Strings opArgs) case qResolve: { for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) - cout << format("%1%\n") % fixPath(*i); + cout << format("%1%\n") % followLinksToStorePath(*i); break; } @@ -403,7 +410,7 @@ static void opReadLog(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { - Path path = useDeriver(fixPath(*i)); + Path path = useDeriver(followLinksToStorePath(*i)); Path logPath = (format("%1%/%2%/%3%") % nixLogDir % drvsLogDir % baseNameOf(path)).str(); @@ -460,7 +467,7 @@ static void opCheckValidity(Strings opFlags, Strings opArgs) for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) { - Path path = fixPath(*i); + Path path = followLinksToStorePath(*i); if (!store->isValidPath(path)) if (printInvalid) cout << format("%1%\n") % path; @@ -535,7 +542,7 @@ static void opDelete(Strings opFlags, Strings opArgs) PathSet pathsToDelete; for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) - pathsToDelete.insert(fixPath(*i)); + pathsToDelete.insert(followLinksToStorePath(*i)); PathSet dummy; PrintFreed freed(true, false); diff --git a/tests/dummy b/tests/dummy deleted file mode 100644 index 557db03de..000000000 --- a/tests/dummy +++ /dev/null @@ -1 +0,0 @@ -Hello World diff --git a/tests/hash.sh b/tests/hash.sh index b3f3fa5bf..5022ea246 100644 --- a/tests/hash.sh +++ b/tests/hash.sh @@ -1,7 +1,7 @@ source common.sh try () { - echo -n "$2" > $TEST_ROOT/vector + printf "%s" "$2" > $TEST_ROOT/vector hash=$($nixhash $EXTRA --flat --type "$1" $TEST_ROOT/vector) if test "$hash" != "$3"; then echo "hash $1, expected $3, got $hash" diff --git a/tests/init.sh b/tests/init.sh index b3470f4de..b5b9ac9b0 100644 --- a/tests/init.sh +++ b/tests/init.sh @@ -79,6 +79,20 @@ sed "s|^$|PATH='$PATH'|" < $NIX_DATA_DIR/nix/corepkgs/nar/nar.sh > tmp chmod +x tmp mv tmp $NIX_DATA_DIR/nix/corepkgs/nar/nar.sh +# An uberhack for Mac OS X 10.5: download-using-manifests uses Perl, +# and Perl links against Darwin's libutil.dylib (in /usr/lib), but +# when running "make check", the libtool wrapper script around the Nix +# binaries sets DYLD_LIBRARY_PATH so that Perl finds Nix's (completely +# different) libutil --- so it barfs. So generate a shell wrapper +# around download-using-manifests that clears DYLD_LIBRARY_PATH. +mv $NIX_BIN_DIR/nix/download-using-manifests.pl $NIX_BIN_DIR/nix/download-using-manifests.pl.real +cat > $NIX_BIN_DIR/nix/download-using-manifests.pl < ./dummy +outPath="$(NIX_STORE_DIR=/foo $nixinstantiate --readonly-mode hash-check.nix)" +if test "$outPath" != "/foo/lfy1s6ca46rm5r6w4gg9hc0axiakjcnm-dependencies.drv"; then + echo "hashDerivationModulo appears broken, got $outPath" + exit 1 fi diff --git a/tests/user-envs.sh b/tests/user-envs.sh index 614c30ceb..edb6da0bf 100644 --- a/tests/user-envs.sh +++ b/tests/user-envs.sh @@ -2,6 +2,8 @@ source common.sh clearProfiles +set -x + # Query installed: should be empty. test "$($nixenv -p $profiles/test -q '*' | wc -l)" -eq 0 @@ -71,6 +73,15 @@ echo $outPath10 $nixenv -p $profiles/test -i "$outPath10" $nixenv -p $profiles/test -q '*' | grep -q foo-1.0 +# Uninstall foo-1.0, using a symlink to its store path. +ln -sfn $outPath10/bin/foo $TEST_ROOT/symlink +$nixenv -p $profiles/test -e $TEST_ROOT/symlink +if $nixenv -p $profiles/test -q '*' | grep -q foo; then false; fi + +# Install foo-1.0, now using a symlink to its store path. +$nixenv -p $profiles/test -i $TEST_ROOT/symlink +$nixenv -p $profiles/test -q '*' | grep -q foo + # Delete all old generations. $nixenv -p $profiles/test --delete-generations old