Compare commits

..

158 Commits

Author SHA1 Message Date
Wouter den Breejen
6af66436f9 2008-03-04 14:16:16 +00:00
Wouter den Breejen
b6659d4425 Script to automatically checkout and create a snix release. 2008-03-04 13:30:53 +00:00
Wouter den Breejen
ab649814fc Merged trunk R.10943 back in 2008-03-04 12:15:55 +00:00
Wouter den Breejen
bffb03eae1 makeValidityRegistration only supports store paths for now .... 2008-02-07 00:06:04 +00:00
Wouter den Breejen
2bf4fcb7cd Merged trunk back in: 10154->10531. 2008-02-06 23:58:00 +00:00
Wouter den Breejen
a34a198006 Merged the Nix sources from the trunk from R9751 to R10133 for my State Nix project. 2008-01-13 16:36:27 +00:00
Wouter den Breejen
55b07d65b1 Merged trunk R9751 back in. 2007-11-19 11:47:41 +00:00
Wouter den Breejen
4e11da960c 2007-11-09 09:50:17 +00:00
Wouter den Breejen
1164d6a389 Merged to R9561; Fixed initial snapshot bug. 2007-10-31 15:08:22 +00:00
Wouter den Breejen
c28742f633 Now using ln -snf to ensure symlinks are overwritten; Fixed --showstatepaths 2007-10-26 10:02:58 +00:00
Wouter den Breejen
7e0dcc5dcb Runtime state arguments added to nix-state. 2007-10-23 14:02:25 +00:00
Wouter den Breejen
c0dceea9f0 2007-10-22 13:22:56 +00:00
Wouter den Breejen
588356c30a Replaced calls to drvFromPath with database calls. 2007-10-19 16:43:37 +00:00
Wouter den Breejen
1747d649c5 2007-10-19 13:42:17 +00:00
Wouter den Breejen
53e31381fa State dirs/files to be versioned and state rights (user,grp,chmod) are now store in the db. Thuss we can remove their derivations at garbage collection time. 2007-10-18 17:45:31 +00:00
Wouter den Breejen
2d84c9e50c Garbage Collection for state paths now works. (altough we don't set locks on state paths or handle cyclic references) 2007-10-18 13:33:50 +00:00
Wouter den Breejen
a699c6b330 fix for queryStoreReferences 2007-10-18 12:08:53 +00:00
Wouter den Breejen
84d00db70b Used Rsync for reverting state. 2007-10-17 11:16:57 +00:00
Wouter den Breejen
138973a6d5 setSnapshot & build-stateinfo fixes 2007-10-16 17:11:18 +00:00
Wouter den Breejen
d8e9dc2775 Garbage collection - gcKeepDerivations bug 2007-10-15 19:17:30 +00:00
Wouter den Breejen
ef37776094 Added more state garbage collection code 2007-10-12 17:18:39 +00:00
Wouter den Breejen
60a32fcbf3 Fixed recursive build error 2007-10-12 14:01:43 +00:00
Wouter den Breejen
0ee803935e Recursive build error.... *2 2007-10-12 10:05:17 +00:00
Wouter den Breejen
65ba1f3008 Recursive build error.... 2007-10-12 10:04:58 +00:00
Wouter den Breejen
16410fc714 Merged to R9439. Fixed a computeFSClosure bug. The state garbage colletor basically works, Missing items: State locks, shared state and Topological sort 2007-10-10 15:55:00 +00:00
Wouter den Breejen
7d82fd16e9 Merged R9433 2007-10-09 21:12:02 +00:00
Wouter den Breejen
8b31968c61 Merged to R9429 2007-10-08 14:53:37 +00:00
Wouter den Breejen
67022b7cca Merged latest trunk revision R9332 into my state branch :) 2007-10-08 14:09:02 +00:00
Wouter den Breejen
a94ea0fd61 Merged R9217 2007-10-08 14:04:55 +00:00
Wouter den Breejen
ca3d96222a Merged R9207 2007-10-08 12:47:47 +00:00
Wouter den Breejen
13b632ca57 Fixes to decodeValidPathInfo and cleanups 2007-10-08 12:24:02 +00:00
Wouter den Breejen
dacf2e0e87 Merged R9105 2007-10-08 11:58:34 +00:00
Wouter den Breejen
00602dd20c Merged R9063 2007-10-08 10:41:41 +00:00
Wouter den Breejen
546ca6e8bc Merged R8864 2007-10-08 10:26:21 +00:00
Wouter den Breejen
854e155b2c Merged R8636 2007-10-08 10:20:43 +00:00
Wouter den Breejen
8e9c7d9338 Merged R8632 2007-10-08 10:15:18 +00:00
Wouter den Breejen
3800f55b54 Merging the trunk back into my branch: just merged revision 8628 2007-10-07 14:32:42 +00:00
Wouter den Breejen
d69dd855d5 Added some state-specific garbage collection code (not complete yet) 2007-10-05 19:33:27 +00:00
Wouter den Breejen
43d93e5e64 Replaced cp for rsync to copy state 2007-10-03 09:46:22 +00:00
Wouter den Breejen
d0458acb7c Implemented runtime --share= and --unshare options. Fixed some things. 2007-10-02 15:52:50 +00:00
Wouter den Breejen
86f0fd8341 Fixed ~ and * to expand in cp and ln commands. 2007-09-19 22:00:43 +00:00
Wouter den Breejen
4c32f38047 2007-09-19 14:26:16 +00:00
Wouter den Breejen
f435abcdb6 Fixed recalculated drv path issue. 2007-09-18 17:01:17 +00:00
Wouter den Breejen
51cff21c92 Fixed sharing issue. Created unshare method. 2007-09-18 15:10:48 +00:00
Wouter den Breejen
315cd18337 2007-09-17 15:38:13 +00:00
Wouter den Breejen
e80c7bda4c 2007-09-11 16:22:07 +00:00
Wouter den Breejen
ed55982085 Fixed remote issues 2007-09-05 14:13:50 +00:00
Wouter den Breejen
35e239af33 EOF 2007-09-04 17:09:26 +00:00
Wouter den Breejen
89ab441fd2 Changed the [solid-state-dependencies] list in the derivation to a single variable 'externalState' (since we also have a single state path) which can, for instance, be set to ~/.mozilla-test in the case of firefox (not bugfree yet) 2007-09-03 19:22:09 +00:00
Wouter den Breejen
68cb244c90 Fixed bugs in revertToRevision and getSharedWithPathSetRecTxn. Users can now also revert to older revisions. 2007-09-03 12:13:22 +00:00
Wouter den Breejen
094c69ad19 2007-08-31 15:19:55 +00:00
Wouter den Breejen
ec7b0afb08 Fixed showrevisions. added commit/run/scan only options 2007-08-30 18:51:19 +00:00
Wouter den Breejen
30cf65af26 Fixed some more remote-store store bugs. Users can now add state store components with nix-env. Paths in /nix/state are now chowned and chmodded to their owners 2007-08-30 18:20:20 +00:00
Wouter den Breejen
627afcc1aa Fixed a lot of remote store issues. But there is still a bug with 32bit unsigned integers: 'implementation cannot deal with > 32-bit integers' 2007-08-28 15:22:27 +00:00
Wouter den Breejen
2e7539bd27 Added state marshall functions in RemoteStore.cc (still unfinished in Nix-worker.cc) 2007-08-27 18:54:05 +00:00
Wouter den Breejen
bdcce95a39 Added / Removed state functions to the Store API 2007-08-27 13:09:24 +00:00
Wouter den Breejen
53a6b9aaa5 * Fixed very old transactional bug that caused a freeze sometimes
* State components that get their state at runtime can now be (un)installed with nix-env
2007-08-17 15:35:34 +00:00
Wouter den Breejen
05297240ea fixed some hard links 2007-08-16 13:44:53 +00:00
Wouter den Breejen
53c907ca09 Fixed ugly '--hello' exception in builder.pl 2007-08-14 17:54:05 +00:00
Wouter den Breejen
5a9cfdeb6e bugfixes 2007-08-14 17:34:45 +00:00
Wouter den Breejen
4089bd5f19 State is now maintained (their paths are automatically shared), unless sharedState is set in the nix-expr, when a new version with the same drv-name of the component is installed 2007-08-13 15:35:12 +00:00
Wouter den Breejen
7424d72098 Partially integrated state components (startscripts) into nix-env 2007-08-10 15:39:02 +00:00
Wouter den Breejen
13f321e397 State revisions are now printed like this: Rev. 01 @ Mon Aug 6 15:48:37 2007 (1186408117) -- Initial build revision. 2007-08-06 15:01:39 +00:00
Wouter den Breejen
696f1fd5e2 before allowing comments to revisions 2007-08-06 12:13:53 +00:00
Wouter den Breejen
af8c5697be Cleaned up code, fixed some TODO's 2007-08-03 16:25:59 +00:00
Wouter den Breejen
bd25de8d88 Fixed referrer issue 2007-08-03 14:50:05 +00:00
Wouter den Breejen
5e0716bbbb Fixed referrer issue 2007-08-03 14:46:53 +00:00
Wouter den Breejen
7d91f62b71 before removing referrer code 2007-08-03 10:30:39 +00:00
Wouter den Breejen
4fb9070fbd before removing referrer code 2007-08-03 10:28:58 +00:00
Wouter den Breejen
83ec65edf5 2007-07-27 16:22:53 +00:00
Wouter den Breejen
856251df03 Fixed revert issue 2007-07-26 11:39:55 +00:00
Wouter den Breejen
0fc5accd86 Replaced SVN by Ext3COW as a backend for state (still some things need to happen: reverting doesn't go right in all cases yet) 2007-07-25 21:52:33 +00:00
Wouter den Breejen
dc4395b737 2007-07-24 12:47:28 +00:00
Wouter den Breejen
a07ba681cc 2007-07-23 15:03:36 +00:00
Wouter den Breejen
45bb1ae6a5 Added ext3cow lib 2007-07-23 14:38:23 +00:00
Wouter den Breejen
e3034da88b 2007-07-23 14:36:36 +00:00
Wouter den Breejen
00f39f88f7 adjusted queryReferences/Referrers to handle shared state paths. 2007-07-20 11:03:30 +00:00
Wouter den Breejen
7f2140d17f Before adjusting queryReferences/Referrers to handle shared state paths 2007-07-19 12:25:38 +00:00
Wouter den Breejen
b46db4dea7 2007-07-18 11:19:41 +00:00
Wouter den Breejen
c0bd494865 Firefox can now be brought under state control, however, the symlink ~/.mozilla/firefox/ --> /nix/state/...../ can not (yet) be created automatically at build time since ~/ is set to /homeless-shelter/ ... 2007-07-13 18:37:25 +00:00
Wouter den Breejen
b6974f2ae6 before adding solid-state dependencies to be able to support state for components that can't be configured to store state in /nix/state/.../ (like firefox) 2007-07-13 13:02:43 +00:00
Wouter den Breejen
6392da5f90 Files and directorys are now properly 'svn deleted' 2007-07-13 11:48:57 +00:00
Wouter den Breejen
e33a1e4e74 coputeFSClosure is now transactional, state will now be commited after the component has been build 2007-07-12 15:59:16 +00:00
Wouter den Breejen
f3dabd6206 before making computeFSClosure recursively transactional ..... (adding Transaction txn) 2007-07-12 14:46:15 +00:00
Wouter den Breejen
7bfed0c104 2007-07-12 11:34:17 +00:00
Wouter den Breejen
96a62bb7e6 2007-07-12 10:51:10 +00:00
Wouter den Breejen
36b79c7135 before moving some functions to nix-state 2007-07-11 13:40:29 +00:00
Wouter den Breejen
ba437f451e 2007-07-10 09:23:42 +00:00
Wouter den Breejen
b378df6484 2007-07-09 21:30:11 +00:00
Wouter den Breejen
fdc2686460 Rectification: isStateComponentTxn should not be removed, the error was caused by a bug in scanAndUpdateAllReferencesTxn 2007-07-09 14:57:45 +00:00
Wouter den Breejen
b7654ab716 before removing isStateComponentTxn 2007-07-09 14:30:57 +00:00
Wouter den Breejen
9257f16c85 Besides directorys, single files can now also be versioned (or excluded) 2007-07-09 11:59:29 +00:00
Wouter den Breejen
bc2fbabc12 Fixed bugs, cleaned up some code 2007-07-09 00:28:38 +00:00
Wouter den Breejen
afb445957d States can now be (recursively) rolled back and forward :) 2007-07-08 22:59:44 +00:00
Wouter den Breejen
9f00b42f38 downscaled to 1 repos per statePath 2007-07-08 22:40:16 +00:00
Wouter den Breejen
cce4156232 before downscaling to 1 repos per statePath 2007-07-08 19:58:16 +00:00
Wouter den Breejen
ca5fc7c582 major update 2007-07-08 19:02:08 +00:00
Wouter den Breejen
cc7d4c8bd7 2007-07-06 19:15:05 +00:00
Wouter den Breejen
40161d0be1 runProgram backup2 2007-07-06 15:20:46 +00:00
Wouter den Breejen
0a4a3a1b68 runProgram backup2 2007-07-06 15:18:37 +00:00
Wouter den Breejen
4f483aad0f runProgram backup 2007-07-06 15:12:20 +00:00
Wouter den Breejen
eb1f179eac separated references and referrers both into 4 tables: links from: component or state to: state or component 2007-07-04 18:53:13 +00:00
Wouter den Breejen
9d7438db9f Before seperation of dbs references_state and references (and referrers) 2007-07-04 12:32:19 +00:00
Wouter den Breejen
c65c296ce0 Before trying to install STLdb4 .... 2007-07-03 13:50:16 +00:00
Wouter den Breejen
ad2b815b5e added scanAndUpdateAllReferencesTxn(..) moving on to create a db-table that can save state-revision-closures and state-revision-reference-closures 2007-07-02 19:15:10 +00:00
Wouter den Breejen
1c3ec86c39 Fixed bug in build.cc All paths are now correctly scanned for the statpaths from the derivation inputs 2007-06-29 20:45:37 +00:00
Wouter den Breejen
c370c9f535 adjusted to: void computeFSClosure(const Path & path, PathSet & paths, const bool & withComponents, const bool & withState, bool flipDirection) 2007-06-29 15:24:51 +00:00
Wouter den Breejen
7eb2f61797 Before adjusting computeFSClosure 2007-06-29 14:56:32 +00:00
Wouter den Breejen
b32691da2b registerValidPath can now also take state paths as arguments, nix-store still cannot 2007-06-28 18:59:07 +00:00
Wouter den Breejen
04dd3fdf34 Bugfix: Before adjusting registerValidPath to also be able to take state paths 2007-06-28 17:12:02 +00:00
Wouter den Breejen
22473597ec merged executeAndPrintShellCommand to runProgram 2007-06-28 13:20:45 +00:00
Wouter den Breejen
b9fe3f00c1 merged executeAndPrintShellCommand to runProgram 2007-06-28 13:17:03 +00:00
Wouter den Breejen
729933062b before merging executeAndPrintShellCommand to runProgram 2007-06-28 11:11:09 +00:00
Wouter den Breejen
1c0b052243 before merging executeAndPrintShellCommand to runProgram 2007-06-28 11:05:11 +00:00
Wouter den Breejen
3d22bd50b3 nix-state now works, state is recursively commited (when necessary) 2007-06-27 15:43:16 +00:00
Wouter den Breejen
c0dcfed3c3 New state queries for nix-store now work:
--requisites / -R: print all paths necessary to realise a path
--requisites-withstate: same as --requisites but now also including state paths
--references: print all paths referenced by the given path
--references-state: print all state paths referenced by the given path  
--referrers: print all paths directly refering to the given path
--referrers-state: print all state paths directly refering to the given path
--referrers-closure: print all paths (in)directly refering to the given path
--referrers-closure-withstate: same as --referrers-closure but now also including state paths
2007-06-22 14:59:03 +00:00
Wouter den Breejen
6351b7e728 added dbValidStatePaths, StatePaths are now also registered as valid and can be query'd on validity 2007-06-22 14:04:06 +00:00
Wouter den Breejen
51fad07fbd Before adding dbValidStatePaths 2007-06-22 13:03:06 +00:00
Wouter den Breejen
0e41b191bf 2007-06-21 16:47:48 +00:00
Wouter den Breejen
a4fda31ad5 Before editting get-drvs.hh: DrvInfo 2007-06-21 13:26:58 +00:00
Wouter den Breejen
235c91dd7f State paths can now be scanned and queryed (references), referres still need to be added 2007-06-19 15:23:00 +00:00
Wouter den Breejen
5164a77aab Before moving scanForStateReferences(...) 2007-06-19 13:05:45 +00:00
Wouter den Breejen
b1cc9e9a45 Before moving scanForStateReferences(...) 2007-06-19 13:04:05 +00:00
Wouter den Breejen
bdecf3bdbc In the middle of adding state references to derivations and the db... 2007-06-18 19:54:31 +00:00
Wouter den Breejen
5e59387d40 Before giving all store-state-runtime-paths a unique hash storepath 2007-06-14 14:16:53 +00:00
Wouter den Breejen
df43c1e5b9 Before adjusting getStateReferencesClosure_ 2007-06-13 16:18:42 +00:00
Wouter den Breejen
184443d18d Before adjusting getStateReferencesClosure_ 2007-06-13 15:18:57 +00:00
Wouter den Breejen
bc0af4449a dont commit binarys... 2007-06-12 21:03:56 +00:00
Wouter den Breejen
76f5c8ba07 Almost finished the identifier/user/multiple-derivations mod 2007-06-12 21:01:55 +00:00
Wouter den Breejen
b909d57f5d broken, in the middle of edditting user / drv mod 2007-06-12 19:08:05 +00:00
Wouter den Breejen
fe04276aef before adjusting derivers table 2007-06-12 12:48:35 +00:00
Wouter den Breejen
95ce7e04b7 Nix now includes the username into the hash calculation, statepaths are also recomputed at buildtime so they cannot be spoofed 2007-06-11 16:43:32 +00:00
Wouter den Breejen
267ccc589d Nix now understands the difference between runtime-state-components and non-runtime-state-compontens. Components and Derivations are now properly (re)build/derived (or not) when necessary. 2007-06-08 16:00:55 +00:00
Wouter den Breejen
fd2b8271e4 Fixed a bug in the auto-deleted-checkout part of the commit bash script, Had to use a hack to get bash to support 2D arrays.... 2007-06-07 18:59:20 +00:00
Wouter den Breejen
255bf5f04b Fixed a bug in the auto-deleted-checkout part of the commit bash script, Had to use a hack to get bash to support 2D arrays.... 2007-06-07 18:39:22 +00:00
Wouter den Breejen
01062b0563 Removed collision-bug between repositorys, each group of repositorys and each individual repository has now a scannable unique hash 2007-06-07 14:08:57 +00:00
Wouter den Breejen
79d5604780 Changed commit script: it recursively walkes through all dirs itself now, uses svn stat where needed, and doesnt use svn add *,svn revert anymore and is much faster 2007-06-07 13:16:38 +00:00
Wouter den Breejen
7166ad8eba Completed updateStateDerivation(Path storepath) method 2007-06-04 19:41:46 +00:00
Wouter den Breejen
bcf9d3ab2f 2007-06-04 16:51:15 +00:00
Wouter den Breejen
9c46444641 Before creating multiple derivation - component instances 2007-05-31 17:18:13 +00:00
Wouter den Breejen
986a50ac78 cleanup old shell script 2007-05-30 17:17:04 +00:00
Wouter den Breejen
25117fd165 the command /nixstate/nix/bin/nix-state --run /nix/store/sig2qgvaayydrwy5hn6b2dm5r2ayhv5s-hellohardcodedstateworld-1.0 now causes state to be checked and comitted 2007-05-30 17:16:25 +00:00
Wouter den Breejen
653e557e81 Before modifying commit shell script 2007-05-30 11:27:01 +00:00
Wouter den Breejen
cbd0d39583 Added beginnnings of getStatePathClosure and GetDrv in local-store.cc, next: setting up variables in nix-state to recursively commit state 2007-05-29 15:42:44 +00:00
Wouter den Breejen
fbd1b78a9d Finished set-up for nix-state, now: adding runtime state parameters & exclude state-identifier as input from state-hash 2007-05-29 11:34:54 +00:00
Wouter den Breejen
0a303ea2c0 before changing db schema 2007-05-25 12:27:36 +00:00
Wouter den Breejen
c9e78a973a Created commit shell script; next adding nix-state 2007-05-24 15:08:12 +00:00
Wouter den Breejen
97eb8c32a0 created sub commit scripts 2007-05-22 16:57:36 +00:00
Wouter den Breejen
86b053dd80 Fixed backwards compatible hack & added state creation call after build 2007-05-22 13:19:27 +00:00
Wouter den Breejen
73995157e3 nixstate is now backwards comptible (because of some ugly hack ..) 2007-05-22 12:14:16 +00:00
Wouter den Breejen
09b8b7efbc Added backwards compatib. but still something... remains that changes the hashes .... :( 2007-05-21 23:42:20 +00:00
Wouter den Breejen
802d7f40bd Small fix 2007-05-21 21:56:34 +00:00
Wouter den Breejen
5cac336820 Repositorys are created, state dirs are checked out automatically 2007-05-21 21:34:49 +00:00
Wouter den Breejen
3fc0b0da58 build error 2007-05-20 12:29:55 +00:00
Wouter den Breejen
8a7874d77d in the middle of adding nixStoreState ... 2007-05-18 19:50:58 +00:00
Wouter den Breejen
4c63f18dcc added state options and state locations into drv 2007-05-16 10:16:10 +00:00
Wouter den Breejen
b712f0f019 First commit 2007-05-15 09:26:33 +00:00
Eelco Dolstra
1a793c60ce * Branch for state support in Nix. 2007-04-05 11:45:20 +00:00
235 changed files with 12202 additions and 7944 deletions

View File

@@ -1,19 +1,23 @@
SUBDIRS = externals src scripts corepkgs doc misc tests
EXTRA_DIST = substitute.mk nix.spec nix.spec.in bootstrap.sh \
nix.conf.example NEWS version
svn-revision nix.conf.example NEWS
include ./substitute.mk
nix.spec: nix.spec.in
rpm: nix.spec dist
rpm $(EXTRA_RPM_FLAGS) -ta $(distdir).tar.gz
relname:
echo -n $(distdir) > relname
install-data-local: init-state
$(INSTALL) -d $(DESTDIR)$(sysconfdir)/nix
$(INSTALL_DATA) $(srcdir)/nix.conf.example $(DESTDIR)$(sysconfdir)/nix
if ! test -e $(DESTDIR)$(sysconfdir)/nix/nix.conf; then \
$(INSTALL_DATA) $(srcdir)/nix.conf.example $(DESTDIR)$(sysconfdir)/nix/nix.conf; \
fi
$(INSTALL) -d $(DESTDIR)$(docdir)
$(INSTALL_DATA) README $(DESTDIR)$(docdir)/
if INIT_STATE
@@ -29,18 +33,29 @@ init-state:
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/profiles
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/gcroots
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/temproots
$(INSTALL) $(INIT_FLAGS) $(GROUP_WRITABLE) -d $(DESTDIR)$(localstatedir)/nix/gcroots/tmp
$(INSTALL) $(INIT_FLAGS) $(GROUP_WRITABLE) -d $(DESTDIR)$(localstatedir)/nix/gcroots/channels
ln -sfn $(localstatedir)/nix/profiles $(DESTDIR)$(localstatedir)/nix/gcroots/profiles
$(INSTALL) $(INIT_FLAGS) -d $(DESTDIR)$(localstatedir)/nix/userpool
-$(INSTALL) $(INIT_FLAGS) -m 1777 -d $(DESTDIR)$(storedir)
$(INSTALL) $(INIT_FLAGS) -m 1777 -d $(DESTDIR)$(prefix)/store
$(INSTALL) $(INIT_FLAGS) $(GROUP_WRITABLE) -d $(DESTDIR)$(localstatedir)/nix/manifests
ln -sfn $(localstatedir)/nix/manifests $(DESTDIR)$(localstatedir)/nix/gcroots/manifests
# $(bindir)/nix-store --init
else
init-state:
endif
NEWS:
$(MAKE) -C doc/manual NEWS.txt
init-ext3cow-header-hack:
@echo "Symlinking ext3cow header file into src"
ln -sf $(ext3cowheader) src/libext3cow/
svn-revision:
svnversion . > svn-revision
all: init-ext3cow-header-hack
all-local: NEWS
NEWS: doc/manual/NEWS.txt
cp $(srcdir)/doc/manual/NEWS.txt NEWS

9
README
View File

@@ -1,10 +1,9 @@
Nix is a purely functional package manager. For installation and
usage instructions, please read the manual, which can be found in
`docs/manual/manual.html', and additionally at the Nix website at
<http://nixos.org/>.
For installation and usage instructions, please read the manual, which
can be found in `docs/manual/manual.html', and additionally at the Nix
website at <http://www.cs.uu.nl/groups/ST/Trace/Nix>.
Acknowledgments
This product includes software developed by the OpenSSL Project for
use in the OpenSSL Toolkit (http://www.OpenSSL.org/).
use in the OpenSSL Toolkit (http://www.OpenSSL.org/)

3
TODO Normal file
View File

@@ -0,0 +1,3 @@
- runtimeStateArgs now must be set to someting (or it will see it as a hardcoded path)
- import and export of state paths
-

View File

@@ -1,117 +1,184 @@
{
ATerm library conservatively scans for GC roots
Memcheck:Cond
fun:*
fun:AT_collect_minor
fun:mark_memory_young
fun:mark_phase_young
}
{
ATerm library conservatively scans for GC roots
Memcheck:Cond
fun:*
fun:*
fun:AT_isValidSymbol
fun:mark_memory_young
fun:mark_phase_young
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:AT_isValidSymbol
fun:mark_memory_young
fun:mark_phase_young
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:mark_memory_young
fun:mark_phase_young
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:AT_isInsideValidTerm
fun:mark_memory_young
fun:mark_phase_young
}
{
ATerm library conservatively scans for GC roots
Memcheck:Cond
fun:AT_isInsideValidTerm
fun:mark_memory_young
fun:mark_phase_young
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:mark_memory_young
fun:mark_phase_young
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:AT_markTerm_young
fun:mark_memory_young
fun:mark_phase_young
}
{
ATerm library conservatively scans for GC roots
Memcheck:Cond
fun:AT_markTerm_young
fun:mark_memory_young
fun:mark_phase_young
}
{
ATerm library conservatively scans for GC roots
Memcheck:Cond
fun:mark_memory
fun:mark_phase
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:mark_memory
fun:mark_phase
}
{
ATerm library conservatively scans for GC roots
Memcheck:Cond
fun:AT_isValidSymbol
fun:mark_memory
fun:mark_phase
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:AT_isValidSymbol
fun:mark_memory
fun:mark_phase
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:AT_isInsideValidTerm
fun:mark_memory
fun:mark_phase
}
{
ATerm library conservatively scans for GC roots
Memcheck:Cond
fun:AT_isInsideValidTerm
fun:mark_memory
fun:mark_phase
}
{
ATerm library conservatively scans for GC roots
Memcheck:Cond
fun:AT_markTerm
fun:mark_memory
fun:mark_phase
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:AT_markTerm
fun:mark_memory
fun:mark_phase
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:AT_markTerm
fun:mark_memory
fun:mark_phase
}
{
ATerm library conservatively scans for GC roots
Memcheck:Cond
fun:mark_phase_young
fun:AT_collect_minor
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:*
fun:mark_phase_young
fun:AT_collect_minor
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value8
fun:*
fun:AT_collect_minor
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value4
fun:*
fun:*
fun:AT_collect_minor
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value8
fun:*
fun:*
fun:AT_collect_minor
}
{
ATerm library conservatively scans for GC roots
Memcheck:Addr4
fun:*
fun:AT_collect_minor
}
{
ATerm library conservatively scans for GC roots
Memcheck:Addr8
fun:*
fun:AT_collect_minor
}
{
ATerm library conservatively scans for GC roots
<insert a suppression name here>
Memcheck:Cond
fun:*
fun:AT_collect
fun:AT_isValidSymbol
fun:mark_phase_young
fun:AT_collect_minor
}
{
ATerm library conservatively scans for GC roots
<insert a suppression name here>
Memcheck:Value4
fun:*
fun:AT_collect
fun:AT_isValidSymbol
fun:mark_phase_young
fun:AT_collect_minor
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value8
fun:*
fun:AT_collect
}
{
ATerm library conservatively scans for GC roots
Memcheck:Addr4
fun:*
fun:AT_collect
}
{
ATerm library conservatively scans for GC roots
Memcheck:Addr8
fun:*
fun:AT_collect
}
{
ATerm library conservatively scans for GC roots
<insert a suppression name here>
Memcheck:Value4
fun:*
fun:*
fun:AT_collect
fun:AT_isInsideValidTerm
fun:mark_phase_young
fun:AT_collect_minor
}
{
ATerm library conservatively scans for GC roots
Memcheck:Value8
fun:*
fun:*
fun:AT_collect
}
{
ATerm library conservatively scans for GC roots
<insert a suppression name here>
Memcheck:Cond
fun:*
fun:*
fun:AT_collect
fun:AT_isInsideValidTerm
fun:mark_phase_young
fun:AT_collect_minor
}

View File

@@ -1,6 +1,6 @@
#! /bin/sh -e
mkdir -p config
libtoolize --copy
libtoolize --force --copy
aclocal
autoheader
automake --add-missing --copy

View File

@@ -1,9 +1,24 @@
AC_INIT(nix, m4_esyscmd([echo -n $(cat ./version)$VERSION_SUFFIX]))
AC_INIT(nix, 0.12)
AC_CONFIG_SRCDIR(README)
AC_CONFIG_AUX_DIR(config)
AM_INIT_AUTOMAKE([dist-bzip2 foreign])
# Change to `1' to produce a `stable' release (i.e., the `preREVISION'
# suffix is not added).
STABLE=0
AC_DEFINE_UNQUOTED(NIX_VERSION, ["$VERSION"], [Nix version.])
# Put the revision number in the version.
if test "$STABLE" != "1"; then
if REVISION=`test -d $srcdir/.svn && svnversion -n $srcdir 2> /dev/null`; then
VERSION=${VERSION}pre${REVISION}
elif REVISION=`cat $srcdir/svn-revision 2> /dev/null`; then
VERSION=${VERSION}pre${REVISION}
fi
fi
AC_DEFINE_UNQUOTED(NIX_VERSION, ["$VERSION"], [version])
AC_PREFIX_DEFAULT(/nix)
AC_CANONICAL_HOST
@@ -39,49 +54,23 @@ case $sys_name in
esac
AC_ARG_WITH(system, AC_HELP_STRING([--with-system=SYSTEM],
[Platform identifier (e.g., `i686-linux').]),
[platform identifier (e.g., `i686-linux')]),
system=$withval, system="${machine_name}-${sys_name}")
AC_MSG_RESULT($system)
AC_SUBST(system)
AC_DEFINE_UNQUOTED(SYSTEM, ["$system"], [platform identifier (`cpu-os')])
# State should be stored in /nix/var, unless the user overrides it explicitly.
test "$localstatedir" = '${prefix}/var' && localstatedir=/nix/var
# Whether to produce a statically linked binary. On Cygwin, this is
# the default: dynamically linking against the ATerm DLL does work,
# except that it requires the ATerm "lib" directory to be in $PATH, as
# Windows doesn't have anything like an RPATH embedded in executable.
# Since this is kind of annoying, we use static libraries for now.
AC_ARG_ENABLE(static-nix, AC_HELP_STRING([--enable-static-nix],
[produce statically linked binaries]),
static_nix=$enableval, static_nix=no)
if test "$sys_name" = cygwin; then
static_nix=yes
fi
if test "$static_nix" = yes; then
AC_DISABLE_SHARED
AC_ENABLE_STATIC
fi
# Windows-specific stuff.
if test "$sys_name" = "cygwin"; then
# We cannot delete open files.
AC_DEFINE(CANNOT_DELETE_OPEN_FILES, 1, [Whether it is impossible to delete open files.])
# Shared libraries don't work, currently.
AC_DISABLE_SHARED
AC_ENABLE_STATIC
fi
# Solaris-specific stuff.
if test "$sys_name" = "sunos"; then
# Solaris requires -lsocket -lnsl for network functions
ADDITIONAL_NETWORK_LIBS="-lsocket -lnsl"
AC_SUBST(ADDITIONAL_NETWORK_LIBS)
fi
AC_PROG_CC
AC_PROG_CXX
@@ -94,7 +83,8 @@ AC_PROG_LIBTOOL
# Use 64-bit file system calls so that we can support files > 2 GiB.
AC_SYS_LARGEFILE
CFLAGS="-D_FILE_OFFSET_BITS=64 $CFLAGS"
CXXFLAGS="-D_FILE_OFFSET_BITS=64 $CXXFLAGS"
# Check for pubsetbuf.
@@ -104,15 +94,13 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <iostream>
using namespace std;
static char buf[1024];]],
[[cerr.rdbuf()->pubsetbuf(buf, sizeof(buf));]])],
[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_PUBSETBUF, 1, [Whether pubsetbuf is available.])],
[AC_MSG_RESULT(yes) AC_DEFINE(HAVE_PUBSETBUF, 1, [whether pubsetbuf is available])],
AC_MSG_RESULT(no))
AC_LANG_POP(C++)
# Check for chroot support (requires chroot() and bind mounts).
AC_CHECK_FUNCS([chroot])
AC_CHECK_FUNCS([unshare])
AC_CHECK_HEADERS([sched.h], [], [], [])
AC_CHECK_HEADERS([sys/param.h], [], [], [])
AC_CHECK_HEADERS([sys/mount.h], [], [],
[#ifdef HAVE_SYS_PARAM_H
@@ -121,17 +109,12 @@ AC_CHECK_HEADERS([sys/mount.h], [], [],
])
# Check for <locale>.
# Check for <locale>
AC_LANG_PUSH(C++)
AC_CHECK_HEADERS([locale], [], [], [])
AC_LANG_POP(C++)
# Check whether we have the personality() syscall, which allows us to
# do i686-linux builds on x86_64-linux machines.
AC_CHECK_HEADERS([sys/personality.h])
AC_DEFUN([NEED_PROG],
[
AC_PATH_PROG($1, $2)
@@ -141,10 +124,11 @@ fi
])
NEED_PROG(curl, curl)
NEED_PROG(bash, bash)
NEED_PROG(shell, bash)
NEED_PROG(patch, patch)
AC_PATH_PROG(xmllint, xmllint, false)
AC_PATH_PROG(xsltproc, xsltproc, false)
AC_PATH_PROG(jing, jing, false) # needed because xmllint --relaxng seems broken
AC_PATH_PROG(w3m, w3m, false)
AC_PATH_PROG(flex, flex, false)
AC_PATH_PROG(bison, bison, false)
@@ -152,7 +136,6 @@ NEED_PROG(perl, perl)
NEED_PROG(tar, tar)
AC_PATH_PROG(dot, dot)
AC_PATH_PROG(dblatex, dblatex)
AC_PATH_PROG(gzip, gzip)
AC_PATH_PROG(openssl_prog, openssl, openssl) # if not found, call openssl in $PATH
AC_SUBST(openssl_prog)
@@ -190,9 +173,40 @@ AC_SUBST(xmlflags)
AC_ARG_WITH(store-dir, AC_HELP_STRING([--with-store-dir=PATH],
[path of the Nix store]),
storedir=$withval, storedir='/nix/store')
storedir=$withval, storedir='${prefix}/store')
AC_SUBST(storedir)
AC_ARG_WITH(store-state-dir, AC_HELP_STRING([--with-store-state-dir=PATH],
[path of the Nix state store]),
storestatedir=$withval, storestatedir='${prefix}/state')
AC_SUBST(storestatedir)
AC_ARG_WITH(bdb, AC_HELP_STRING([--with-bdb=PATH],
[prefix of Berkeley DB]),
bdb=$withval, bdb=)
AM_CONDITIONAL(HAVE_BDB, test -n "$bdb")
if test -z "$bdb"; then
bdb_lib='-L${top_builddir}/externals/inst-bdb/lib -ldb_cxx'
bdb_include='-I${top_builddir}/externals/inst-bdb/include'
else
bdb_lib="-L$bdb/lib -ldb_cxx"
bdb_include="-I$bdb/include"
fi
AC_SUBST(bdb_lib)
AC_SUBST(bdb_include)
AC_ARG_WITH(ext3cow-header, AC_HELP_STRING([--with-ext3cow-header=PATH],
[path of the ext3cow header ext3cow_fs.h]),
ext3cowheader=$withval, ext3cowheader=)
AC_SUBST(ext3cowheader)
AC_CHECK_HEADER(${ext3cowheader})
NEED_PROG(rsync, rsync)
AC_ARG_WITH(rsync, AC_HELP_STRING([--with-rsync=PATH],
[path to the rsync binary.]),
rsync=$withval)
AC_SUBST(rsync)
AC_ARG_WITH(aterm, AC_HELP_STRING([--with-aterm=PATH],
[prefix of CWI ATerm library]),
aterm=$withval, aterm=)
@@ -218,7 +232,7 @@ if test -n "$openssl"; then
LDFLAGS="-L$openssl/lib -lcrypto $LDFLAGS"
CFLAGS="-I$openssl/include $CFLAGS"
CXXFLAGS="-I$openssl/include $CXXFLAGS"
AC_DEFINE(HAVE_OPENSSL, 1, [Whether to use OpenSSL.])
AC_DEFINE(HAVE_OPENSSL, 1, [whether to use OpenSSL])
fi
AC_ARG_WITH(bzip2, AC_HELP_STRING([--with-bzip2=PATH],
@@ -231,7 +245,7 @@ if test -z "$bzip2"; then
bzip2_lib='-L${top_builddir}/externals/inst-bzip2/lib -lbz2'
bzip2_include='-I${top_builddir}/externals/inst-bzip2/include'
# The binary will be copied to $libexecdir.
bzip2_bin='${libexecdir}/nix'
bzip2_bin='${libexecdir}'
# But for testing, we have to use the temporary copy :-(
bzip2_bin_test='${top_builddir}/externals/inst-bzip2/bin'
else
@@ -239,7 +253,7 @@ else
bzip2_include="-I$bzip2/include"
bzip2_bin="$bzip2/bin"
bzip2_bin_test="$bzip2/bin"
fi
fi
AC_SUBST(bzip2_lib)
AC_SUBST(bzip2_include)
AC_SUBST(bzip2_bin)
@@ -261,24 +275,15 @@ AC_CHECK_FUNCS([setresuid setreuid lchown])
# Nice to have, but not essential.
AC_CHECK_FUNCS([strsignal])
AC_CHECK_FUNCS([posix_fallocate])
# This is needed if ATerm or bzip2 are static libraries,
# This is needed if ATerm, Berkeley DB or bzip2 are static libraries,
# and the Nix libraries are dynamic.
if test "$(uname)" = "Darwin"; then
LDFLAGS="-all_load $LDFLAGS"
fi
if test "$static_nix" = yes; then
# `-all-static' has to be added at the end of configure, because
# the C compiler doesn't know about -all-static (it's filtered out
# by libtool, but configure doesn't use libtool).
LDFLAGS="-all-static $LDFLAGS"
fi
AM_CONFIG_HEADER([config.h])
AC_CONFIG_FILES([Makefile
externals/Makefile
@@ -289,7 +294,9 @@ AC_CONFIG_FILES([Makefile
src/libutil/Makefile
src/libstore/Makefile
src/libmain/Makefile
src/libext3cow/Makefile
src/nix-store/Makefile
src/nix-state/Makefile
src/nix-hash/Makefile
src/libexpr/Makefile
src/nix-instantiate/Makefile

View File

@@ -3,24 +3,39 @@
use strict;
use Cwd;
use IO::Handle;
use Fcntl;
STDOUT->autoflush(1);
my $out = $ENV{"out"};
mkdir "$out", 0755 || die "error creating $out";
sub readlink_or_StateWrapper;
my $symlinks = 0;
my %path_state_identifier = ();
my %priorities;
my $nixBinDir = $ENV{"nixBinDir"};
my $nixStore = $ENV{"nixStore"};
# For each activated package, create symlinks.
sub createLinks {
my $srcDir = shift;
#Lookup each $stateIdentifiers in $path_state_identifier
#we strip $srcDir to its rootdir e.g. /nix/store/......./
my @srcDirParts = split /\// , substr($srcDir, length ($nixStore), length ($srcDir));
my $srcDirRoot = $nixStore . "/" . $srcDirParts[1];
# print "srcDirRoot $srcDirRoot \n";
my $dstDir = shift;
my $priority = shift;
my $pkgStateIdentifier = $path_state_identifier{$srcDirRoot}; # We have to look it up each time since recursion can change the $srcDir, but not the identifier
#print "createLinks $srcDir to $dstDir with iden $pkgStateIdentifier \n";
my @srcFiles = glob("$srcDir/*");
@@ -29,20 +44,21 @@ sub createLinks {
$baseName =~ s/^.*\///g; # strip directory
my $dstFile = "$dstDir/$baseName";
# Urgh, hacky...
if ($srcFile =~ /\/propagated-build-inputs$/ ||
# Urgh, hacky...
if ($srcFile =~ /\/propagated-build-inputs$/ ||
$srcFile =~ /\/nix-support$/ ||
$srcFile =~ /\/perllocal.pod$/ ||
$srcFile =~ /\/info\/dir$/ ||
$srcFile =~ /\/log$/)
{
# Do nothing.
}
}
elsif (-d $srcFile) {
lstat $dstFile;
#go recursive on directorys
if (-d _) {
createLinks($srcFile, $dstFile, $priority);
}
@@ -53,13 +69,15 @@ sub createLinks {
die "collission between directory `$srcFile' and non-directory `$target'";
}
unlink $dstFile or die "error unlinking `$dstFile': $!";
mkdir $dstFile, 0755 ||
die "error creating directory `$dstFile': $!";
mkdir $dstFile, 0755 || die "error creating directory `$dstFile': $!";
createLinks($target, $dstFile, $priorities{$dstFile});
createLinks($srcFile, $dstFile, $priority);
}
else {
#print "1ST DIR LINK $srcFile to $dstFile with iden $pkgStateIdentifier \n";
symlink($srcFile, $dstFile) ||
die "error creating link `$dstFile': $!";
$priorities{$dstFile} = $priority;
@@ -69,23 +87,67 @@ sub createLinks {
else {
if (-l $dstFile) {
my $target = readlink $dstFile;
my $prevPriority = $priorities{$dstFile};
die ( "Collission between `$srcFile' and `$target'. "
. "Suggested solution: use `nix-env --set-flag "
. "priority NUMBER PKGNAME' to change the priority of "
. "one of the conflicting packages.\n" )
if $prevPriority == $priority;
next if $prevPriority < $priority;
unlink $dstFile or die;
}
symlink($srcFile, $dstFile) ||
die "error creating link `$dstFile': $!";
$priorities{$dstFile} = $priority;
$symlinks++;
}
# print "ELSE LINK $srcFile to $dstFile with iden $pkgStateIdentifier \n";
# if we have a state component with a identifier different then ""
if($pkgStateIdentifier ne "__NOSTATE__" && $pkgStateIdentifier ne ""){
my @pathparts = split /\// , $srcFile;
my $parentDir = $pathparts[scalar(@pathparts) - 2];
if( $parentDir eq "bin" || $parentDir eq "sbin"){ #hacky....
print "STATELINK $srcFile to $dstFile - $pkgStateIdentifier \n";
my $new_dstFile;
my $new_stateIdentifier;
if($pkgStateIdentifier eq "__EMTPY__"){
$new_dstFile = $dstFile;
$new_stateIdentifier = "";
}
else{
$new_dstFile = "$dstFile-$pkgStateIdentifier";
$new_stateIdentifier = $pkgStateIdentifier;
}
# We also check with -e if the wrapperscript-file exists, and if is it a symlink (with -l)
if (-l $new_dstFile || -e $new_dstFile) {
my $target = readlink_or_StateWrapper $new_dstFile;
die "(state) collission between `$srcFile' and `$target' (over $new_dstFile)";
}
sysopen (DSTFILEHANDLE, $new_dstFile, O_RDWR|O_EXCL|O_CREAT, 0755);
printf DSTFILEHANDLE "#! @shell@ \n";
printf DSTFILEHANDLE "$nixBinDir/nix-state --run --identifier=$new_stateIdentifier $srcFile \"\$@\" \n";
close (DSTFILEHANDLE);
}
}
elsif($pkgStateIdentifier ne "__NOSTATE__" && $pkgStateIdentifier eq ""){ #TODO we now dont create symlinks for state packages with a empty identifier
#TODO but we must do it if there is no normal non-state pacakge
}
else {
if (-l $dstFile || -e $dstFile) {
my $target = readlink_or_StateWrapper $dstFile;
my $prevPriority = $priorities{$dstFile};
die ( "Collission between `$srcFile' and `$target'. "
. "Suggested solution: use `nix-env --set-flag "
. "priority NUMBER PKGNAME' to change the priority of "
. "one of the conflicting packages.\n" )
if $prevPriority == $priority;
next if $prevPriority < $priority;
unlink $dstFile or die;
}
# print "2ND LINK $srcFile to $dstFile with iden $pkgStateIdentifier \n";
symlink($srcFile, $dstFile) ||
die "error creating link `$dstFile': $!";
$priorities{$dstFile} = $priority;
$symlinks++;
}
}
}
}
@@ -116,6 +178,24 @@ sub addPkg {
}
}
sub readlink_or_StateWrapper {
my $src = shift;
my $target;
if (-l $src)
{ $target = readlink $src; }
else{
open(DAT, $src) || die("Could not open file!");
my @raw_data=<DAT>;
close(DAT);
$target = $raw_data[1];
}
return $target
}
my @stateIdentifiers = split ' ', $ENV{"stateIdentifiers"};
my $si_counter = 0;
# Convert the stuff we get from the environment back into a coherent
# data type.
@@ -131,15 +211,23 @@ my %pkgs;
for (my $n = 0; $n < scalar @paths; $n++) {
$pkgs{$paths[$n]} =
{ active => $active[$n]
, priority => $priority[$n] };
, priority => $priority[$n]
, stateidentifier => $stateIdentifiers[$n]
};
$path_state_identifier{$paths[$n]} = $stateIdentifiers[$n];
}
# Symlink to the packages that have been installed explicitly by the
# user.
foreach my $pkg (sort (keys %pkgs)) {
#print $pkg, " ", $pkgs{$pkg}->{priority}, "\n";
#print "SP: $pkg \n";
#print "SI: $pkgs{$pkg}->{stateidentifier} \n";
#print "PR: $pkgs{$pkg}->{priority} \n";
addPkg($pkg, $pkgs{$pkg}->{priority}) if $pkgs{$pkg}->{active} ne "false";
$si_counter++;
}
@@ -149,6 +237,7 @@ foreach my $pkg (sort (keys %pkgs)) {
# priority in case of collisions.
my $priorityCounter = 1000; # don't care about collisions
while (scalar(keys %postponed) > 0) {
my @pkgDirs = keys %postponed;
%postponed = ();
foreach my $pkgDir (sort @pkgDirs) {
@@ -156,8 +245,7 @@ while (scalar(keys %postponed) > 0) {
}
}
print STDERR "created $symlinks symlinks in user environment\n";
symlink($ENV{"manifest"}, "$out/manifest") or die "cannot create manifest";

View File

@@ -1,11 +1,13 @@
{system, derivations, manifest}:
{system, derivations, stateIdentifiers, manifest, nixBinDir, nixStore}:
derivation {
name = "user-environment";
system = system;
builder = ./builder.pl;
stateIdentifiers = stateIdentifiers;
manifest = manifest;
inherit nixBinDir nixStore;
# !!! grmbl, need structured data for passing this in a clean way.
paths = derivations;

View File

@@ -8,15 +8,9 @@ inputs=($inputs)
for ((n = 0; n < ${#inputs[*]}; n += 2)); do
channelName=${inputs[n]}
channelTarball=${inputs[n+1]}
echo "unpacking channel $channelName"
@bunzip2@ < $channelTarball | @tar@ xf -
if test -e */channel-name; then
channelName="$(@coreutils@/cat */channel-name)"
fi
nr=1
attrName=$(echo $channelName | @tr@ -- '- ' '__')
dirName=$attrName

21
createRelease.sh Executable file
View File

@@ -0,0 +1,21 @@
#! /bin/sh -e
dir1=releases
dir2=nix-state
mkdir -p $dir1
cd $dir1
rm -rf $dir2
mkdir -p $dir2
cd $dir2
svn co https://svn.cs.uu.nl:12443/repos/trace/nix/branches/state ./
revision=`svn info | grep ^Revision | sed 's/Revision: //g'`
cd ..
date=`date +%Y%m%d`
tarfile=snix-${date}-rev${revision}.tar.gz
tar -cvf $tarfile \
--preserve-permissions \
--atime-preserve \
--gzip \
--verbose \
--no-ignore-command-error \
$dir2/

View File

@@ -1 +1 @@
SUBDIRS = manual
SUBDIRS =

View File

@@ -6,12 +6,7 @@ XSLTPROC = $(xsltproc) $(xmlflags) \
--param xref.with.number.and.title 1 \
--param toc.section.depth 3 \
--param admon.style \'\' \
--param callout.graphics.extension \'.gif\' \
--param contrib.inline.enabled 0
dblatex_opts = \
-P doc.collab.show=0 \
-P latex.output.revhistory=0
--param callout.graphics.extension \'.gif\'
# Note: we use GIF for now, since the PNGs shipped with Docbook aren't
# transparent.
@@ -19,24 +14,27 @@ dblatex_opts = \
man1_MANS = nix-env.1 nix-build.1 nix-store.1 nix-instantiate.1 \
nix-collect-garbage.1 nix-push.1 nix-pull.1 \
nix-prefetch-url.1 nix-channel.1 \
nix-pack-closure.1 nix-unpack-closure.1 \
nix-install-package.1 nix-hash.1 nix-copy-closure.1
man8_MANS = nix-worker.8
FIGURES = figures/user-environments.png
MANUAL_SRCS = manual.xml introduction.xml installation.xml \
package-management.xml writing-nix-expressions.xml builtins.xml \
build-farm.xml \
$(man1_MANS:.1=.xml) $(man8_MANS:.8=.xml) \
$(man1_MANS:.1=.xml) \
troubleshooting.xml bugs.xml opt-common.xml opt-common-syn.xml \
env-common.xml quick-start.xml nix-lang-ref.xml glossary.xml \
conf-file.xml release-notes.xml \
style.css images
# Note: RelaxNG validation requires xmllint >= 2.7.4.
manual.is-valid: $(MANUAL_SRCS) version.txt
$(XMLLINT) --noout --nonet --xinclude --noxincludenode --relaxng $(docbookrng)/docbook.rng $<
# $(XMLLINT) --xinclude $< | $(XMLLINT) --noout --nonet --relaxng $(docbookrng)/docbook.rng -
if test "$(jing)" != "false"; then \
$(XMLLINT) --xinclude $< | $(jing) $(docbookrng)/docbook.rng /dev/fd/0; \
else \
echo "Not validating."; \
fi
touch $@
version.txt:
@@ -51,7 +49,7 @@ manual.html: $(MANUAL_SRCS) manual.is-valid images
manual.pdf: $(MANUAL_SRCS) manual.is-valid images
if test "$(dblatex)" != ""; then \
$(dblatex) $(dblatex_opts) manual.xml; \
$(dblatex) manual.xml; \
else \
echo "Please install dblatex and rerun configure."; \
exit 1; \
@@ -78,16 +76,12 @@ NEWS.txt: release-notes.xml
all-local: manual.html NEWS.html NEWS.txt
install-data-local: manual.html
$(INSTALL) -d $(DESTDIR)$(docdir)/manual
$(INSTALL_DATA) manual.html $(DESTDIR)$(docdir)/manual
ln -sf manual.html $(DESTDIR)$(docdir)/manual/index.html
$(INSTALL_DATA) style.css $(DESTDIR)$(docdir)/manual
cp -r images $(DESTDIR)$(docdir)/manual/images
$(INSTALL) -d $(DESTDIR)$(docdir)/manual/figures
$(INSTALL_DATA) $(FIGURES) $(DESTDIR)$(docdir)/manual/figures
$(INSTALL) -d $(DESTDIR)$(docdir)/release-notes
$(INSTALL_DATA) NEWS.html $(DESTDIR)$(docdir)/release-notes/index.html
$(INSTALL_DATA) style.css $(DESTDIR)$(docdir)/release-notes/
$(INSTALL) -d $(DESTDIR)$(datadir)/nix/manual
$(INSTALL_DATA) manual.html $(DESTDIR)$(datadir)/nix/manual
$(INSTALL_DATA) style.css $(DESTDIR)$(datadir)/nix/manual
cp -r images $(DESTDIR)$(datadir)/nix/manual/images
$(INSTALL) -d $(DESTDIR)$(datadir)/nix/manual/figures
$(INSTALL_DATA) $(FIGURES) $(DESTDIR)$(datadir)/nix/manual/figures
images:
mkdir images

1
doc/manual/NEWS.txt Normal file
View File

@@ -0,0 +1 @@
New state nix version by wouter ...

View File

@@ -56,7 +56,7 @@ build farm, since:
<para>TODO</para>
<para>The sources of the Nix build farm are at <link
xlink:href='https://svn.nixos.org/repos/nix/release/trunk'/>.</para>
xlink:href='https://svn.cs.uu.nl:12443/repos/trace/release/trunk'/>.</para>
</section>
@@ -85,7 +85,7 @@ nix@scratchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto
<para>An example build hook can be found in the Nix build farm
sources: <link
xlink:href='https://svn.nixos.org/repos/nix/release/trunk/common/distributed/build-remote.pl'
xlink:href='https://svn.cs.uu.nl:12443/repos/trace/release/trunk/common/distributed/build-remote.pl'
/>. It should be suitable for most purposes, with maybe some minor
adjustments. It uses <command>ssh</command> and
<command>rsync</command> to copy the build inputs and outputs and

View File

@@ -77,25 +77,18 @@ attrValues = attrs: map (name: builtins.getAttr name attrs) (builtins.attrNames
if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
This allows a Nix expression to fall back gracefully on older Nix
installations that dont have the desired built-in
function.</para></listitem>
installations that dont have the desired built-in function.
However, in that case you should not write
</varlistentry>
<programlisting>
if builtins ? getEnv then __getEnv "PATH" else ""</programlisting>
<varlistentry><term><function>builtins.compareVersions</function>
<replaceable>s1</replaceable> <replaceable>s2</replaceable></term>
<listitem><para>Compare two strings representing versions and
return <literal>-1</literal> if version
<replaceable>s1</replaceable> is older than version
<replaceable>s2</replaceable>, <literal>0</literal> if they are
the same, and <literal>1</literal> if
<replaceable>s1</replaceable> is newer than
<replaceable>s2</replaceable>. The version comparison algorithm
is the same as the one used by <link
linkend="ssec-version-comparisons"><command>nix-env
-u</command></link>.</para></listitem>
This Nix expression will trigger an “undefined variable” error on
older Nix versions since <function>__getEnv</function> doesnt
exist. <literal>builtins.getEnv</literal>, on the other hand, is
safe since <literal>builtins</literal> always exists and attribute
selection is lazy, so its only performed if the test
succeeds.</para></listitem>
</varlistentry>
@@ -153,16 +146,6 @@ if builtins ? getEnv then builtins.getEnv "PATH" else ""</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.div</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return the quotient of the integers
<replaceable>e1</replaceable> and
<replaceable>e2</replaceable>.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.filterSource</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
@@ -324,16 +307,6 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.intersectAttrs</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return an attribute set consisting of the
attributes in the set <replaceable>e2</replaceable> that also
exist in the set <replaceable>e1</replaceable>.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.isAttrs</function>
<replaceable>e</replaceable></term>
@@ -364,36 +337,6 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.isString</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to a string, and
<literal>false</literal> otherwise.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.isInt</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to a int, and
<literal>false</literal> otherwise.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.isBool</function>
<replaceable>e</replaceable></term>
<listitem><para>Return <literal>true</literal> if
<replaceable>e</replaceable> evaluates to a bool, and
<literal>false</literal> otherwise.</para></listitem>
</varlistentry>
<varlistentry><term><function>isNull</function>
<replaceable>e</replaceable></term>
@@ -409,15 +352,6 @@ x: x + 456</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.length</function>
<replaceable>e</replaceable></term>
<listitem><para>Return the length of the list
<replaceable>e</replaceable>.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.lessThan</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
@@ -474,31 +408,6 @@ map (x: "foo" + x) ["bar" "bla" "abc"]</programlisting>
</varlistentry>
<varlistentry><term><function>builtins.mul</function>
<replaceable>e1</replaceable> <replaceable>e2</replaceable></term>
<listitem><para>Return the product of the integers
<replaceable>e1</replaceable> and
<replaceable>e2</replaceable>.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.parseDrvName</function>
<replaceable>s</replaceable></term>
<listitem><para>Split the string <replaceable>s</replaceable> into
a package name and version. The package name is everything up to
but not including the first dash followed by a digit, and the
version is everything following that dash. The result is returned
in an attribute set <literal>{name, version}</literal>. Thus,
<literal>builtins.parseDrvName "nix-0.12pre12876"</literal>
returns <literal>{name = "nix"; version =
"0.12pre12876";}</literal>.</para></listitem>
</varlistentry>
<varlistentry><term><function>builtins.pathExists</function>
<replaceable>path</replaceable></term>

View File

@@ -60,6 +60,27 @@ env-keep-derivations = false
</varlistentry>
<varlistentry xml:id="conf-gc-reserved-space"><term><literal>gc-reserved-space</literal></term>
<listitem><para>This option specifies how much space should be
reserved in normal use so that the garbage collector can run
succesfully. Since the garbage collector must perform Berkeley DB
transactions, it needs some disk space for itself. However, when
the disk is full, this space is not available, so the collector
would not be able to run precisely when it is most needed.</para>
<para>For this reason, when Nix is run, it allocates a file
<filename>/nix/var/nix/db/reserved</filename> of the size
specified by this option. When the garbage collector is run, this
file is deleted before the Berkeley DB environment is opened.
This should give it enough room to proceed.</para>
<para>The default is <literal>1048576</literal> (1
MiB).</para></listitem>
</varlistentry>
<varlistentry><term><literal>env-keep-derivations</literal></term>
<listitem><para>If <literal>false</literal> (default), derivations
@@ -233,17 +254,7 @@ build-use-chroot = /dev /proc /bin</programlisting>
<filename>configure</filename> at build time.</para></listitem>
</varlistentry>
<varlistentry><term><literal>fsync-metadata</literal></term>
<listitem><para>If set to <literal>true</literal>, changes to the
Nix store metadata (in <filename>/nix/var/nix/db</filename>) are
synchronously flushed to disk. This improves robustness in case
of system crashes, but reduces performance. The default is
<literal>false</literal>.</para></listitem>
</varlistentry>
</variablelist>

View File

@@ -151,12 +151,12 @@ $ mount -o bind /mnt/otherdisk/nix /nix</screen>
<para>On the basis of this information, and whatever persistent
state the build hook keeps about other machines and their current
load, it has to decide what to do with the build. It should print
out on standard error one of the following responses (terminated by
a newline, <literal>"\n"</literal>):
out on file descriptor 3 one of the following responses (terminated
by a newline, <literal>"\n"</literal>):
<variablelist>
<varlistentry><term><literal># decline</literal></term>
<varlistentry><term><literal>decline</literal></term>
<listitem><para>The build hook is not willing or able to perform
the build; the calling Nix process should do the build itself,
@@ -164,7 +164,7 @@ $ mount -o bind /mnt/otherdisk/nix /nix</screen>
</varlistentry>
<varlistentry><term><literal># postpone</literal></term>
<varlistentry><term><literal>postpone</literal></term>
<listitem><para>The build hook cannot perform the build now, but
can do so in the future (e.g., because all available build slots
@@ -174,7 +174,7 @@ $ mount -o bind /mnt/otherdisk/nix /nix</screen>
</varlistentry>
<varlistentry><term><literal># accept</literal></term>
<varlistentry><term><literal>accept</literal></term>
<listitem><para>The build hook has accepted the
build.</para></listitem>
@@ -185,12 +185,37 @@ $ mount -o bind /mnt/otherdisk/nix /nix</screen>
</para>
<para>After sending <literal># accept</literal>, the hook should
read one line from standard input, which will be the string
<literal>okay</literal>. It can then proceed with the build.
Before sending <literal>okay</literal>, Nix will store in the hooks
current directory a number of text files that contain information
about the derivation:
<para>If the build hook accepts the build, it is possible that it is
no longer necessary to do the build because some other process has
performed the build in the meantime. To prevent races, the hook
must read from file descriptor 4 a single line that tells it whether
to continue:
<variablelist>
<varlistentry><term><literal>cancel</literal></term>
<listitem><para>The build has already been done, so the hook
should exit.</para></listitem>
</varlistentry>
<varlistentry><term><literal>okay</literal></term>
<listitem><para>The hook should proceed with the build. At this
point, the calling Nix process has acquired locks on the output
path, so no other Nix process will perform the
build.</para></listitem>
</varlistentry>
</variablelist>
</para>
<para>If the hook has been told to proceed, Nix will store in the
hooks current directory a number of text files that contain
information about the derivation:
<variablelist>
@@ -230,9 +255,7 @@ $ mount -o bind /mnt/otherdisk/nix /nix</screen>
<para>The hook should copy the inputs to the remote machine,
register the validity of the inputs, perform the remote build, and
copy the outputs back to the local machine. An exit code other than
<literal>0</literal> indicates that the hook has failed. An exit
code equal to 100 means that the remote build failed (as opposed to,
e.g., a network error).</para>
<literal>0</literal> indicates that the hook has failed.</para>
</listitem>
@@ -251,27 +274,6 @@ $ mount -o bind /mnt/otherdisk/nix /nix</screen>
</varlistentry>
<varlistentry xml:id="envar-other-stores"><term><envar>NIX_OTHER_STORES</envar></term>
<listitem><para>This variable contains the paths of remote Nix
installations from whichs paths can be copied, separated by colons.
See <xref linkend="sec-sharing-packages" /> for details. Each path
should be the <filename>/nix</filename> directory of a remote Nix
installation (i.e., not the <filename>/nix/store</filename>
directory). The paths are subject to globbing, so you can set it so
something like <literal>/var/run/nix/remote-stores/*/nix</literal>
and mount multiple remote filesystems in
<literal>/var/run/nix/remote-stores</literal>.</para>
<para>Note that if youre building through the <link
linkend="sec-nix-worker">Nix daemon</link>, the only setting for
this variable that matters is the one that the
<command>nix-worker</command> process uses. So if you want to
change it, you have to restart the daemon.</para></listitem>
</varlistentry>
</variablelist>

View File

@@ -42,22 +42,25 @@ platforms as well.</para>
<section><title>Obtaining Nix</title>
<para>The easiest way to obtain Nix is to download a <link
xlink:href="http://nixos.org/">source distribution</link>. RPMs
xlink:href="http://nix.cs.uu.nl/">source distribution</link>. RPMs
for Red Hat, SuSE, and Fedora Core are also available.</para>
<para>Alternatively, the most recent sources of Nix can be obtained
from its <link
xlink:href="https://svn.nixos.org/repos/nix/nix/trunk">Subversion
xlink:href="https://svn.cs.uu.nl:12443/repos/trace/nix/trunk">Subversion
repository</link>. For example, the following command will check out
the latest revision into a directory called
<filename>nix</filename>:</para>
<screen>
$ svn checkout https://svn.nixos.org/repos/nix/nix/trunk nix</screen>
$ svn checkout https://svn.cs.uu.nl:12443/repos/trace/nix/trunk nix</screen>
<para>Likewise, specific releases can be obtained from the <link
xlink:href="https://svn.nixos.org/repos/nix/nix/tags">tags
directory</link> of the repository.</para>
xlink:href="https://svn.cs.uu.nl:12443/repos/trace/nix/tags">tags
directory</link> of the repository. If you don't have Subversion, you
can also download an automatically generated <link
xlink:href="https://svn.cs.uu.nl:12443/dist/trace/">compressed
tar-file</link> of the head revision of the trunk.</para>
</section>
@@ -96,16 +99,18 @@ ubiquitous 2.5.4a won't. Note that these are only required if you
modify the parser or when you are building from the Subversion
repository.</para>
<para>Nix uses CWI's ATerm library and the bzip2 compressor (including
the bzip2 library). These are included in the Nix source
distribution. If you build from the Subversion repository, you must
download them yourself and place them in the
<para>Nix uses Sleepycat's Berkeley DB, CWI's ATerm library and the
bzip2 compressor (including the bzip2 library). These are included in
the Nix source distribution. If you build from the Subversion
repository, you must download them yourself and place them in the
<filename>externals/</filename> directory. See
<filename>externals/Makefile.am</filename> for the precise URLs of
these packages. Alternatively, if you already have them installed,
you can use <command>configure</command>'s
<option>--with-aterm</option> and <option>--with-bzip2</option>
options to point to their respective locations.</para>
<option>--with-bdb</option>, <option>--with-aterm</option> and
<option>--with-bzip2</option> options to point to their respective
locations. Note that Berkeley DB <emphasis>must</emphasis> be version
4.5; other versions may not have compatible database formats.</para>
</section>
@@ -133,25 +138,16 @@ $ ./bootstrap</screen>
<para>The installation path can be specified by passing the
<option>--prefix=<replaceable>prefix</replaceable></option> to
<command>configure</command>. The default installation directory is
<filename>/usr/local</filename>. You can change this to any location
you like. You must have write permission to the
<filename>/nix</filename>. You can change this to any location you
like. You must have write permission to the
<replaceable>prefix</replaceable> path.</para>
<para>Nix keeps its <emphasis>store</emphasis> (the place where
packages are stored) in <filename>/nix/store</filename> by default.
This can be changed using
<option>--with-store-dir=<replaceable>path</replaceable></option>.</para>
<warning><para>It is best <emphasis>not</emphasis> to change the
installation prefix from its default, since doing so makes it
impossible to use pre-built binaries from the standard Nixpkgs
channels.</para></warning>
<warning><para>It is best <emphasis>not</emphasis> to change the Nix
store from its default, since doing so makes it impossible to use
pre-built binaries from the standard Nixpkgs channels — that is, all
packages will need to be built from source.</para></warning>
<para>Nix keeps state (such as its database and log files) in
<filename>/nix/var</filename> by default. This can be changed using
<option>--localstatedir=<replaceable>path</replaceable></option>.</para>
<para>If you want to rebuild the documentation, pass the full path to
<para>If you want to rebuilt the documentation, pass the full path to
the DocBook RELAX NG schemas and to the DocBook XSL stylesheets using
the
<option>--with-docbook-rng=<replaceable>path</replaceable></option>
@@ -162,26 +158,27 @@ options.</para>
</section>
<section><title>Installing a binary distribution</title>
<section><title>Installing from RPMs</title>
<para>RPM and Deb packages of Nix for a number of different versions
of Fedora, openSUSE, Debian and Ubuntu can be downloaded from <link
xlink:href="http://nixos.org/" />. Once downloaded, the RPMs can be
installed or upgraded using <command>rpm -U</command>. For example,
<para>RPM packages of Nix can be downloaded from <link
xlink:href="http://nix.cs.uu.nl/" />. 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
<literal>glibc</literal> 2.3 or later.</para>
<para>Once downloaded, the RPMs can be installed or upgraded using
<command>rpm -U</command>. For example,
<screen>
$ rpm -U nix-0.13pre18104-1.i386.rpm</screen>
Likewise, for a Deb package:
<screen>
$ dpkg -i nix_0.13pre18104-1_amd64.deb</screen>
$ rpm -U nix-0.5pre664-1.i386.rpm</screen>
</para>
<para>Nix can be uninstalled using <command>rpm -e nix</command> or
<command>dpkg -r nix</command>. After this you should manually remove
the Nix store and other auxiliary data, if desired:
<para>The RPMs install into the directory <filename>/nix</filename>.
Nix can be uninstalled using <command>rpm -e nix</command>. After
this it will be necessary to manually remove the Nix store and other
auxiliary data:
<screen>
$ rm -rf /nix/store
@@ -192,20 +189,18 @@ $ rm -rf /nix/var</screen>
</section>
<!-- TODO: should be updated
<section><title>Upgrading Nix through Nix</title>
<para>You can install the latest stable version of Nix through Nix
itself by subscribing to the channel <link
xlink:href="http://nixos.org/releases/nix/channels/nix-stable" />,
xlink:href="http://nix.cs.uu.nl/dist/nix/channels-v3/nix-stable" />,
or the latest unstable version by subscribing to the channel <link
xlink:href="http://nixos.org/releases/nix/channels/nix-unstable" />.
xlink:href="http://nix.cs.uu.nl/dist/nix/channels-v3/nix-unstable" />.
You can also do a <link linkend="sec-one-click">one-click
installation</link> by clicking on the package links at <link
xlink:href="http://nixos.org/releases/full-index-nix.html" />.</para>
xlink:href="http://nix.cs.uu.nl/dist/nix/" />.</para>
</section>
-->
<section><title>Security</title>
@@ -339,8 +334,8 @@ $ chown -R root /nix/store /nix/var/nix</screen>
</para>
<para>The <link linkend="sec-nix-worker">Nix daemon</link> should be
started as follows (as <literal>root</literal>):
<para>The Nix daemon should be started as follows (as
<literal>root</literal>):
<screen>
$ nix-worker --daemon</screen>

View File

@@ -240,7 +240,7 @@ configuration (e.g., to build configuration files in
possible to easily roll back the entire configuration of the system to
an earlier state. Also, users can install software without root
privileges. For more information and downloads, see the <link
xlink:href="http://nixos.org/">NixOS homepage</link>.</para>
xlink:href="http://nix.cs.uu.nl/nixos/">NixOS homepage</link>.</para>
</simplesect>
@@ -257,15 +257,14 @@ xlink:href="http://nixos.org/">NixOS homepage</link>.</para>
<section><title>About us</title>
<para>Nix was originally developed at the <link
<para>Nix was developed at the <link
xlink:href="http://www.cs.uu.nl/">Department of Information and
Computing Sciences</link>, Utrecht University by the <link
xlink:href="http://www.cs.uu.nl/wiki/Trace/WebHome">TraCE
project</link> (2003-2008). The project was funded by the Software
Engineering Research Program <link
project</link>. The project is funded by the Software Engineering
Research Program <link
xlink:href="http://www.jacquard.nl/">Jacquard</link> to improve the
support for variability in software systems. Further funding is now
provided by the NIRICT LaQuSo Build Farm project.</para>
support for variability in software systems.</para>
</section>
@@ -300,27 +299,27 @@ Lesser General Public License for more details.</para>
<para>Some background information on Nix can be found in a number of
papers. The ICSE 2004 paper <citetitle
xlink:href='http://www.st.ewi.tudelft.nl/~dolstra/pubs/immdsd-icse2004-final.pdf'>Imposing
xlink:href='http://www.cs.uu.nl/~eelco/pubs/immdsd-icse2004-final.pdf'>Imposing
a Memory Management Discipline on Software Deployment</citetitle>
discusses the hashing mechanism used to ensure reliable dependency
identification and non-interference between different versions and
variants of packages. The LISA 2004 paper <citetitle
xlink:href='http://www.st.ewi.tudelft.nl/~dolstra/pubs/nspfssd-lisa2004-final.pdf'>Nix:
xlink:href='http://www.cs.uu.nl/~eelco/pubs/nspfssd-lisa2004-final.pdf'>Nix:
A Safe and Policy-Free System for Software Deployment</citetitle>
gives a more general discussion of Nix from a system-administration
perspective. The CBSE 2005 paper <citetitle
xlink:href='http://www.st.ewi.tudelft.nl/~dolstra/pubs/eupfcdm-cbse2005-final.pdf'>Efficient
xlink:href='http://www.cs.uu.nl/~eelco/pubs/eupfcdm-cbse2005-final.pdf'>Efficient
Upgrading in a Purely Functional Component Deployment Model
</citetitle> is about transparent patch deployment in Nix. The SCM-12
paper <citetitle
xlink:href='http://www.st.ewi.tudelft.nl/~dolstra/pubs/servicecm-scm12-final.pdf'>
xlink:href='http://www.cs.uu.nl/~eelco/pubs/servicecm-scm12-final.pdf'>
Service Configuration Management</citetitle> shows how services (e.g.,
web servers) can be deployed and managed through Nix. A short
overview of NixOS is given in the HotOS XI paper <citetitle
xlink:href="http://www.st.ewi.tudelft.nl/~dolstra/pubs/hotos-final.pdf">Purely
xlink:href="http://www.cs.uu.nl/~eelco/pubs/hotos-final.pdf">Purely
Functional System Configuration Management</citetitle>. The Nix
homepage has <link
xlink:href="http://nixos.org/docs/papers.html">an up-to-date list
xlink:href="http://nix.cs.uu.nl/docs/papers.html">an up-to-date list
of Nix-related papers</link>.</para>
<para>Nix is the subject of Eelco Dolstras PhD thesis <citetitle
@@ -329,7 +328,7 @@ Purely Functional Software Deployment Model</citetitle>, which
contains most of the papers listed above.</para>
<para>Nix has a homepage at <link
xlink:href="http://nixos.org/"/>.</para>
xlink:href="http://nix.cs.uu.nl/"/>.</para>
</section>

View File

@@ -14,10 +14,9 @@
<surname>Dolstra</surname>
</personname>
<affiliation>
<orgname>Delft University of Technology</orgname>
<orgdiv>Department of Software Technology</orgdiv>
<orgname>Utrecht University</orgname>
<orgdiv>Faculty of Science, Department of Information and Computing Sciences</orgdiv>
</affiliation>
<contrib>Author</contrib>
</author>
<copyright>
@@ -25,12 +24,10 @@
<year>2005</year>
<year>2006</year>
<year>2007</year>
<year>2008</year>
<year>2009</year>
<holder>Eelco Dolstra</holder>
</copyright>
<date>September 2009</date>
<date>September 2007</date>
</info>
@@ -51,29 +48,72 @@
<section>
<title>Main commands</title>
<xi:include href="nix-env.xml" />
<xi:include href="nix-instantiate.xml" />
<xi:include href="nix-store.xml" />
<section xml:id="sec-nix-env">
<title>nix-env</title>
<xi:include href="nix-env.xml" />
</section>
<section xml:id="sec-nix-instantiate">
<title>nix-instantiate</title>
<xi:include href="nix-instantiate.xml" />
</section>
<section xml:id="sec-nix-store">
<title>nix-store</title>
<xi:include href="nix-store.xml" />
</section>
</section>
<section>
<title>Utilities</title>
<xi:include href="nix-build.xml" />
<xi:include href="nix-channel.xml" />
<xi:include href="nix-collect-garbage.xml" />
<xi:include href="nix-copy-closure.xml" />
<xi:include href="nix-hash.xml" />
<xi:include href="nix-install-package.xml" />
<xi:include href="nix-prefetch-url.xml" />
<xi:include href="nix-pull.xml" />
<xi:include href="nix-push.xml" />
<xi:include href="nix-worker.xml" />
<section xml:id="sec-nix-build">
<title>nix-build</title>
<xi:include href="nix-build.xml" />
</section>
<section xml:id="sec-nix-channel">
<title>nix-channel</title>
<xi:include href="nix-channel.xml" />
</section>
<section xml:id="sec-nix-collect-garbage">
<title>nix-collect-garbage</title>
<xi:include href="nix-collect-garbage.xml" />
</section>
<section xml:id="sec-nix-copy-closure">
<title>nix-copy-closure</title>
<xi:include href="nix-copy-closure.xml" />
</section>
<section xml:id="sec-nix-hash">
<title>nix-hash</title>
<xi:include href="nix-hash.xml" />
</section>
<section xml:id="sec-nix-install-package">
<title>nix-install-package</title>
<xi:include href="nix-install-package.xml" />
</section>
<section xml:id="sec-nix-pack-closure">
<title>nix-pack-closure</title>
<xi:include href="nix-pack-closure.xml" />
</section>
<section xml:id="sec-nix-prefetch-url">
<title>nix-prefetch-url</title>
<xi:include href="nix-prefetch-url.xml" />
</section>
<section xml:id="sec-nix-pull">
<title>nix-pull</title>
<xi:include href="nix-pull.xml" />
</section>
<section xml:id="sec-nix-push">
<title>nix-push</title>
<xi:include href="nix-push.xml" />
</section>
<section xml:id="sec-nix-unpack-closure">
<title>nix-unpack-closure</title>
<xi:include href="nix-unpack-closure.xml" />
</section>
</section>
</appendix>
<xi:include href="troubleshooting.xml" />
<!-- <xi:include href="bugs.xml" /> -->
<xi:include href="bugs.xml" />
<xi:include href="glossary.xml" />
<appendix>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-build">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-build</refentrytitle>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-channel">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-channel</refentrytitle>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-collect-garbage">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-collect-garbage</refentrytitle>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-copy-closure">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-copy-closure</refentrytitle>
@@ -129,7 +128,7 @@ those paths. If this bothers you, use
<para>Copy Firefox with all its dependencies to a remote machine:
<screen>
$ nix-copy-closure --to alice@itchy.labs $(type -tP firefox)</screen>
$ nix-copy-closure alice@itchy.labs $(type -tP firefox)</screen>
</para>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-env">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-env</refentrytitle>
@@ -527,7 +526,7 @@ upgrading `mozilla-1.2' to `mozilla-1.4'</screen>
</refsection>
<refsection xml:id="ssec-version-comparisons"><title>Versions</title>
<refsection><title>Versions</title>
<para>The upgrade operation determines whether a derivation
<varname>y</varname> is an upgrade of a derivation

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-hash">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-hash</refentrytitle>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-install-package">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-install-package</refentrytitle>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-instantiate">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-instantiate</refentrytitle>

View File

@@ -178,5 +178,100 @@
</productionset>
</sect1>
<sect1>
<title>Semantics</title>
<sect2>
<title>Built-in functions</title>
<para>
The Nix language provides the following built-in function
(<quote>primops</quote>):
</para>
<variablelist>
<varlistentry>
<term><function>import</function>
<replaceable>e</replaceable></term>
<listitem>
<para>
Evaluates the expression <replaceable>e</replaceable>,
which must yield a path value. The Nix expression
stored at this path in the file system is then read,
parsed, and evaluated. Returns the result of the
evaluation of the Nix expression just read.
</para>
<para>
Example: <literal>import ./foo.nix</literal> evaluates
the expression stored in <filename>foo.nix</filename>
(in the directory containing the expression in which the
<function>import</function> occurs).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><function>derivation</function>
<replaceable>e</replaceable></term>
<listitem>
<para>
Evaluates the expression <replaceable>e</replaceable>,
which must yield an attribute set. [...]
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><function>baseNameOf</function>
<replaceable>e</replaceable></term>
<listitem>
<para>
Evaluates the expression <replaceable>e</replaceable>,
which must yield a string value, and returns a string
representing its <emphasis>base name</emphasis>. This
is the substring following the last path separator
(<literal>/</literal>).
</para>
<para>
Example: <literal>baseNameOf "/foo/bar"</literal>
returns <literal>"bar"</literal>, and
<literal>baseNameOf "/foo/bar/"</literal> returns
<literal>""</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><function>toString</function>
<replaceable>e</replaceable></term>
<listitem>
<para>
Evaluates the expression <replaceable>e</replaceable>
and coerces it into a string, if possible. Only
strings, paths, and URIs can be so coerced.
</para>
<para>
Example: <literal>toString
http://www.cs.uu.nl/</literal> returns
<literal>"http://www.cs.uu.nl/"</literal>.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
</sect1>
</appendix>

View File

@@ -0,0 +1,82 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-pack-closure</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="source">Nix</refmiscinfo>
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
</refmeta>
<refnamediv>
<refname>nix-pack-closure</refname>
<refpurpose>pack the closure of a store path into a single file that
can be unpacked with
<command>nix-unpack-closure</command></refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nix-pack-closure</command>
<arg choice='plain' rep='repeat'><replaceable>paths</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>The command <command>nix-pack-closure</command> packs the
contents of the store paths <replaceable>paths</replaceable> and
<emphasis>all their dependencies</emphasis> into a single file, which
is written to standard output. (That is, it
<emphasis>serialises</emphasis> <replaceable>paths</replaceable>.)
The output can then be unpacked into the Nix store of another machine
using <command>nix-unpack-closure</command>.</para>
<para>Together, <command>nix-pack-closure</command> and
<command>nix-unpack-closure</command> provide a quick and easy way to
deploy a package to a different machine. However, as the output of
<command>nix-pack-closure</command> tends to be rather large (since it
contains all dependencies), its not very efficient.
<command>nix-push</command> and <command>nix-pull</command> are more
efficient, but are also a bit more cumbersome to use.</para>
</refsection>
<refsection><title>Examples</title>
<para>To copy some instance of Subversion with all its dependencies to
another machine:
<screen>
$ nix-pack-closure /nix/store/hj232g1r...-subversion-1.3.0 > svn.closure
<lineannotation>Copy <!-- !!! <filename> -->svn.closure to the remote machine, then on the remote machine do:</lineannotation>
$ nix-unpack-closure &lt; svn.closure</screen>
</para>
<para>Copy the program <command>azureus</command> with all its
dependencies to the machine <literal>scratchy</literal>:
<screen>
$ nix-pack-closure $(which azureus) | ssh scratchy nix-unpack-closure</screen>
</para>
<para>As a variation on the previous example, copy
<command>azureus</command>, and also install it in the users profile
on the target machine:
<screen>
$ nix-pack-closure $(which azureus) | ssh scratchy 'nix-env -i $(nix-unpack-closure)'</screen>
</para>
</refsection>
</refentry>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-prefetch-url">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-prefetch-url</refentrytitle>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-pull">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-pull</refentrytitle>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-push">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-push</refentrytitle>

View File

@@ -1,7 +1,6 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-store">
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-store</refentrytitle>
@@ -129,7 +128,6 @@ lrwxrwxrwx 1 ... 2005-03-13 21:10 /home/eelco/bla/result -> /nix/store/1r1134
<arg choice='plain'><option>-r</option></arg>
</group>
<arg choice='plain' rep='repeat'><replaceable>paths</replaceable></arg>
<arg><option>--dry-run</option></arg>
</cmdsynopsis>
</refsection>
@@ -168,11 +166,6 @@ the specified store paths. Realisation is a somewhat overloaded term:
output. (For non-derivations argument, the argument itself is
printed.)</para>
<para>If the <option>--dry-run</option> option is used, then
<command>nix-store</command> will print on standard error a
description of what packages would be built or downloaded, and then
quit.</para>
</refsection>
@@ -211,8 +204,6 @@ linkend="sec-nix-build"><command>nix-build</command></link> does.</para>
<arg choice='plain'><option>--print-dead</option></arg>
<arg choice='plain'><option>--delete</option></arg>
</group>
<arg><option>--max-freed</option> <replaceable>bytes</replaceable></arg>
<arg><option>--max-links</option> <replaceable>nrlinks</replaceable></arg>
</cmdsynopsis>
</refsection>
@@ -267,34 +258,7 @@ the Nix store not reachable via file system references from a set of
</variablelist>
<para>By default, all unreachable paths are deleted. The following
options control what gets deleted and in what order:
<variablelist>
<varlistentry><term><option>--max-freed</option> <replaceable>bytes</replaceable></term>
<listitem><para>Keep deleting paths until at least
<replaceable>bytes</replaceable> bytes have been
deleted, then stop.</para></listitem>
</varlistentry>
<varlistentry><term><option>--max-links</option> <replaceable>nrlinks</replaceable></term>
<listitem><para>Keep deleting paths until the hard link count on
<filename>/nix/store</filename> is less than
<replaceable>nrlinks</replaceable>, then stop. This is useful for
very large Nix stores on filesystems with a 32000 subdirectories
limit (like <literal>ext3</literal>).</para></listitem>
</varlistentry>
</variablelist>
</para>
<para>The behaviour of the collector is also influenced by the <link
<para>The behaviour of the collector is influenced by the <link
linkend="conf-gc-keep-outputs"><literal>gc-keep-outputs</literal></link>
and <link
linkend="conf-gc-keep-derivations"><literal>gc-keep-derivations</literal></link>
@@ -320,13 +284,6 @@ deleting `/nix/store/kq82idx6g0nyzsp2s14gfsc38npai7lf-cairo-1.0.4.tar.gz.drv'
</para>
<para>To delete at least 100 MiBs of unreachable paths:
<screen>
$ nix-store --gc --max-freed $((100 * 1024 * 1024))</screen>
</para>
</refsection>
@@ -404,7 +361,6 @@ error: cannot delete path `/nix/store/zq0h41l75vlb4z45kzgjjmsjxvcv1qk7-mesa-6.4'
<arg choice='plain'><option>--tree</option></arg>
<arg choice='plain'><option>--binding</option> <replaceable>name</replaceable></arg>
<arg choice='plain'><option>--hash</option></arg>
<arg choice='plain'><option>--roots</option></arg>
</group>
<arg><option>--use-output</option></arg>
<arg><option>-u</option></arg>
@@ -587,20 +543,12 @@ query is applied to the target of the symlink.</para>
<varlistentry><term><option>--hash</option></term>
<listitem><para>Prints the SHA-256 hash of the contents of the
store paths <replaceable>paths</replaceable>. Since the hash is
store path <replaceable>paths</replaceable>. Since the hash is
stored in the Nix database, this is a fast
operation.</para></listitem>
</varlistentry>
<varlistentry><term><option>--roots</option></term>
<listitem><para>Prints the garbage collector roots that point,
directly or indirectly, at the store paths
<replaceable>paths</replaceable>.</para></listitem>
</varlistentry>
</variablelist>
</refsection>
@@ -678,18 +626,6 @@ $ gv graph.ps</screen>
</para>
<para>Show every garbage collector root that points to a store path
that depends on <command>svn</command>:
<screen>
$ nix-store -q --roots $(which svn)
/nix/var/nix/profiles/default-81-link
/nix/var/nix/profiles/default-82-link
/nix/var/nix/profiles/per-user/eelco/profile-97-link
</screen>
</para>
</refsection>
@@ -1014,51 +950,7 @@ ktorrent-2.2.1/NEWS
</refsection>
<!--######################################################################-->
<refsection><title>Operation <option>--dump-db</option></title>
<refsection>
<title>Synopsis</title>
<cmdsynopsis>
<command>nix-store</command>
<arg choice='plain'><option>--dump-db</option></arg>
</cmdsynopsis>
</refsection>
<refsection><title>Description</title>
<para>The operation <option>--dump-db</option> writes a dump of the
Nix database to standard output. It can be loaded into an empty Nix
store using <option>--load-db</option>. This is useful for making
backups and when migrating to different database schemas.</para>
</refsection>
</refsection>
<!--######################################################################-->
<refsection><title>Operation <option>--dump-db</option></title>
<refsection>
<title>Synopsis</title>
<cmdsynopsis>
<command>nix-store</command>
<arg choice='plain'><option>--load-db</option></arg>
</cmdsynopsis>
</refsection>
<refsection><title>Description</title>
<para>The operation <option>--load-db</option> reads a dump of the Nix
database created by <option>--dump-db</option> from standard input and
loads it into the Nix database.</para>
</refsection>
</refsection>
<!-- TODO: export, import operations -->
</refentry>

View File

@@ -0,0 +1,42 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude">
<refmeta>
<refentrytitle>nix-unpack-closure</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="source">Nix</refmiscinfo>
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
</refmeta>
<refnamediv>
<refname>nix-unpack-closure</refname>
<refpurpose>unpack the closure of a store path created by <command>nix-pack-closure</command> into the Nix store</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nix-unpack-closure</command>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>The command <command>nix-unpack-closure</command> unpacks the
closure of a set of store paths created by
<command>nix-pack-closure</command> into the local Nix store. The
closure is a single file read from standard input. See the
description of <command>nix-pack-closure</command> for details and
examples.</para>
<para>The top-level paths in the closure (i.e., the paths passed to
the original <command>nix-pack-closure</command> call that created the
closure) are printed on standard output. These paths can be passed,
for instance, to <literal>nix-env -i</literal> to install them into a
user environment on the target machine.</para>
</refsection>
</refentry>

View File

@@ -1,35 +0,0 @@
<refentry xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xml:id="sec-nix-worker">
<refmeta>
<refentrytitle>nix-worker</refentrytitle>
<manvolnum>8</manvolnum>
<refmiscinfo class="source">Nix</refmiscinfo>
<refmiscinfo class="version"><xi:include href="version.txt" parse="text"/></refmiscinfo>
</refmeta>
<refnamediv>
<refname>nix-worker</refname>
<refpurpose>Nix multi-user support daemon</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>nix-worker</command>
<arg choice="plain"><option>--daemon</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsection><title>Description</title>
<para>The Nix daemon is necessary in multi-user Nix installations. It
performs build actions and other operations on the Nix store on behalf
of unprivileged users.</para>
</refsection>
</refentry>

View File

@@ -24,7 +24,6 @@
<arg><option>--fallback</option></arg>
<arg><option>--readonly-mode</option></arg>
<arg><option>--log-type</option> <replaceable>type</replaceable></arg>
<arg><option>--show-trace</option></arg>
<sbr />
</nop>

View File

@@ -251,14 +251,14 @@
<programlisting>
{ # The system (e.g., `i686-linux') for which to build the packages.
system ? builtins.currentSystem
system ? __currentSystem
<replaceable>...</replaceable>
}: <replaceable>...</replaceable></programlisting>
So if you call this Nix expression (e.g., when you do
<literal>nix-env -i <replaceable>pkgname</replaceable></literal>),
the function will be called automatically using the value <link
linkend='builtin-currentSystem'><literal>builtins.currentSystem</literal></link>
linkend='builtin-currentSystem'><literal>__currentSystem</literal></link>
for the <literal>system</literal> argument. You can override this
using <option>--arg</option>, e.g., <literal>nix-env -i
<replaceable>pkgname</replaceable> --arg system
@@ -305,14 +305,6 @@
</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>
</variablelist>

View File

@@ -38,7 +38,7 @@ 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
the latest version from <link
xlink:href='http://nixos.org/releases/full-index-nixpkgs.html' />.</para>
xlink:href='http://nix.cs.uu.nl/dist/nix' />.</para>
<para>Assuming that you have downloaded and unpacked a release of Nix
Packages, you can view the set of available packages in the release:
@@ -118,15 +118,15 @@ available somewhere. This is done using the
containing a <emphasis>manifest</emphasis> describing what binaries
are available. This URL should correspond to the Nix Packages release
that youre using. For instance, if you obtained a release from <link
xlink:href='http://nixos.org/releases/nixpkgs/nixpkgs-0.12pre11712-4lrp7j8x'
/>, then you should do:
xlink:href='http://nix.cs.uu.nl/dist/nix/nixpkgs-0.6pre1554/' />, then
you should do:
<screen>
$ nix-pull http://nixos.org/releases/nixpkgs/nixpkgs-0.12pre11712-4lrp7j8x/MANIFEST</screen>
$ nix-pull http://nix.cs.uu.nl/dist/nix/nixpkgs-0.6pre1554/MANIFEST</screen>
If you then issue the installation command, it should start
downloading binaries from <systemitem
class='fqdomainname'>nixos.org</systemitem>, instead of building
class='fqdomainname'>nix.cs.uu.nl</systemitem>, instead of building
them from source. This might still take a while since all
dependencies must be downloaded, but on a reasonably fast connection
such as an DSL line its on the order of a few minutes.</para>
@@ -331,7 +331,7 @@ default profile, respectively. If the profile doesnt exist, it will
be created automatically. You should be careful about storing a
profile in another location than the <filename>profiles</filename>
directory, since otherwise it might not be used as a root of the
garbage collector (see <xref linkend='sec-garbage-collection'
garbage collector (see section <xref linkend='sec-garbage-collection'
/>).</para>
<para>All <command>nix-env</command> operations work on the profile
@@ -458,7 +458,7 @@ URL.</para>
<command>nix-channel --add</command>, e.g.,
<screen>
$ nix-channel --add http://nixos.org/releases/nixpkgs/channels/nixpkgs-unstable</screen>
$ nix-channel --add http://nix.cs.uu.nl/dist/nix/channels-v3/nixpkgs-unstable</screen>
subscribes you to a channel that always contains that latest version
of the Nix Packages collection. (Instead of
@@ -496,27 +496,31 @@ available in the subscribed channels.</para>
<para>Often, when you want to install a specific package (e.g., from
the <link
xlink:href="http://nixos.org/releases/nixpkgs/nixpkgs-unstable/">Nix
Packages collection</link>), subscribing to a channel is a bit
cumbersome. And channels dont help you at all if you want to install
an older version of a package than the one provided by the current
contents of the channel, or a package that has been removed from the
channel. Thats when <emphasis>one-click installs</emphasis> come in
handy: you can just go to the web page that contains the package,
click on it, and it will be installed with all the necessary
dependencies.</para>
xlink:href="http://nix.cs.uu.nl/dist/nix/nixpkgs-unstable-latest/">Nix
Packages collection</link> or from our <link
xlink:href='http://nix.cs.uu.nl/dist/'>release server</link>),
subscribing to a channel is a bit cumbersome. And channels dont help
you at all if you want to install an older version of a package than
the one provided by the current contents of the channel, or a package
that has been removed from the channel. Thats when
<emphasis>one-click installs</emphasis> come in handy: you can just go
to the web page that contains the package, click on it, and it will be
installed with all the necessary dependencies.</para>
<para>For instance, you can go to <link
xlink:href="http://hydra.nixos.org/jobset/nixpkgs/trunk/channel/latest"
/> and click on any link for the individual packages for your
platform. The first time you do this, your browser will ask what to
do with <literal>application/nix-package</literal> files. You should
open them with <filename>/nix/bin/nix-install-package</filename>.
This will open a window that asks you to confirm that you want to
install the package. When you answer <literal>Y</literal>, the
package and all its dependencies will be installed. This is a binary
deployment mechanism — you get packages pre-compiled for the selected
platform type.</para>
xlink:href="http://nix.cs.uu.nl/dist/nix/nixpkgs-unstable-latest/" />
— or to any older release of Nix Packages — and click on any link for
the individual packages for your platform (say, <link
xlink:href='http://nix.cs.uu.nl/dist/nix/nixpkgs-0.10pre6622/pkgs/subversion-1.4.0-i686-linux.nixpkg'><literal>subversion-1.4.0</literal>
for <literal>i686-linux</literal></link>). The first time you do
this, your browser will ask what to do with
<literal>application/nix-package</literal> files. You should open
them with <filename>/nix/bin/nix-install-package</filename>. This
will open a window that asks you to confirm that you want to install
the package. When you answer <literal>Y</literal>, the package and
all its dependencies will be installed. This is a binary deployment
mechanism — you get packages pre-compiled for the selected platform
type.</para>
<para>You can also install <literal>application/nix-package</literal>
files from the command line directly. See <xref
@@ -525,82 +529,4 @@ linkend='sec-nix-install-package' /> for details.</para>
</section>
<section xml:id="sec-sharing-packages"><title>Sharing packages between machines</title>
<para>Sometimes you want to copy a package from one machine to
another. Or, you want to install some packages and you know that
another machine already has some or all of those packages or their
dependencies. In that case there are mechanisms to quickly copy
packages between machines.</para>
<para>The command <command
linkend="sec-nix-copy-closure">nix-copy-closure</command> copies a Nix
store path along with all its dependencies to or from another machine
via the SSH protocol. It doesnt copy store paths that are already
present on the target machine. For example, the following command
copies Firefox with all its dependencies:
<screen>
$ nix-copy-closure --to alice@itchy.example.org $(type -p firefox)</screen>
See <xref linkend='sec-nix-copy-closure' /> for details.</para>
<para>With <command linkend='refsec-nix-store-export'>nix-store
--export</command> and <command
linkend='refsec-nix-store-import'>nix-store --import</command> you can
write the closure of a store path (that is, the path and all its
dependencies) to a file, and then unpack that file into another Nix
store. For example,
<screen>
$ nix-store --export $(type -p firefox) > firefox.closure</screen>
writes the closure of Firefox to a file. You can then copy this file
to another machine and install the closure:
<screen>
$ nix-store --import &lt; firefox.closure</screen>
Any store paths in the closure that are already present in the target
store are ignored. It is also possible to pipe the export into
another command, e.g. to copy and install a closure directly to/on
another machine:
<screen>
$ nix-store --export $(type -p firefox) | bzip2 | \
ssh alice@itchy.example.org "bunzip2 | nix-store --import"</screen>
But note that <command>nix-copy-closure</command> is generally more
efficient in this example because it only copies paths that are not
already present in the target Nix store.</para>
<para>Finally, if you can mount the Nix store of a remote machine in
your local filesystem, Nix can copy paths from the remote Nix store to
the local Nix store <emphasis>on demand</emphasis>. For instance,
suppose that you mount a remote machine containing a Nix store via
<command
xlink:href="http://fuse.sourceforge.net/sshfs.html">sshfs</command>:
<screen>
$ sshfs alice@itchy.example.org:/ /mnt</screen>
You should then set the <envar>NIX_OTHER_STORES</envar> environment
variable to tell Nix about this remote Nix store:
<screen>
$ export NIX_OTHER_STORES=/mnt/nix</screen>
Then if you do any Nix operation, e.g.
<screen>
$ nix-env -i firefox</screen>
and Nix has to build a path that it sees is already present in
<filename>/mnt/nix</filename>, then it will just copy from there
instead of building it from source.</para>
</section>
</chapter>

View File

@@ -1,6 +1,5 @@
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xml:id="chap-quick-start">
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Quick Start</title>
@@ -11,9 +10,9 @@ to the following chapters.</para>
<orderedlist>
<listitem><para>Download a source tarball, RPM or Deb from <link
xlink:href='http://nixos.org/'/>. Build source distributions using
the regular sequence:
<listitem><para>Download a source tarball or RPM from <link
xlink:href='http://nix.cs.uu.nl/'/>. Build source
distributions using the regular sequence:
<screen>
$ tar xvfj nix-<replaceable>version</replaceable>.tar.bz2
@@ -21,28 +20,20 @@ $ ./configure
$ make
$ make install <lineannotation>(as root)</lineannotation></screen>
This will install the Nix binaries in <filename>/usr/local</filename>
and keep the Nix store and other state in <filename>/nix</filename>.
You can change the former by specifying
<option>--prefix=<replaceable>path</replaceable></option>. The
location of the store can be changed using
<option>--with-store-dir=<replaceable>path</replaceable></option>.
However, you shouldn't change the store location, if at all possible,
since that will make it impossible to use pre-built binaries from the
Nixpkgs channel and other channels. The location of the state can be
changed using
<option>--localstatedir=<replaceable>path</replaceable>.</option></para></listitem>
<listitem><para>You should add
<filename><replaceable>prefix</replaceable>/etc/profile.d/nix.sh</filename>
to your <filename>~/.bashrc</filename> (or some other login
This will install Nix in <filename>/nix</filename>. You shouldn't
change the prefix if at all possible since that will make it
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
<filename>/nix/etc/profile.d/nix.sh</filename> to your
<filename>~/.bashrc</filename> (or some other login
file).</para></listitem>
<listitem><para>Subscribe to the Nix Packages channel.
<screen>
$ nix-channel --add \
http://nixos.org/releases/nixpkgs/channels/nixpkgs-unstable</screen>
http://nix.cs.uu.nl/dist/nix/channels-v3/nixpkgs-unstable</screen>
</para></listitem>
@@ -108,7 +99,7 @@ numbers).</para></listitem>
<listitem><para>You can also install specific packages directly from
your web browser. For instance, you can go to <link
xlink:href="http://hydra.nixos.org/jobset/nixpkgs/trunk/channel/latest" />
xlink:href="http://nix.cs.uu.nl/dist/nix/nixpkgs-unstable-latest/" />
and click on any link for the individual packages for your platform.
Associate <literal>application/nix-package</literal> with the program
<filename>/nix/bin/nix-install-package</filename>. A window should

View File

@@ -8,317 +8,11 @@
<!--==================================================================-->
<section xml:id="ssec-relnotes-0.14"><title>Release 0.14 (TBA)</title>
<para>This release has the following improvements:</para>
<section xml:id="ssec-relnotes-0.12"><title>Release 0.12 (TBA)</title>
<itemizedlist>
<listitem>
<para>The garbage collector now starts deleting garbage much
faster than before. It no longer determines liveness of all paths
in the store, but does so on demand.</para>
</listitem>
<listitem>
<para>Added a new operation, <command>nix-store --query
--roots</command>, that shows the garbage collector roots that
directly or indirectly point to the given store paths.</para>
</listitem>
<listitem>
<para>Removed support for converting Berkeley DB-based Nix
databases to the new schema.</para>
</listitem>
<listitem>
<para>Removed the <option>--use-atime</option> and
<option>--max-atime</option> garbage collector options. They were
not very useful in practice.</para>
</listitem>
<listitem>
<para>A few bug fixes.</para>
</listitem>
</itemizedlist>
</section>
<!--==================================================================-->
<section xml:id="ssec-relnotes-0.13"><title>Release 0.13 (November 5,
2009)</title>
<para>This is primarily a bug fix release. It has some new
features:</para>
<itemizedlist>
<listitem>
<para>Syntactic sugar for writing nested attribute sets. Instead of
<programlisting>
{
foo = {
bar = 123;
xyzzy = true;
};
a = { b = { c = "d"; }; };
}
</programlisting>
you can write
<programlisting>
{
foo.bar = 123;
foo.xyzzy = true;
a.b.c = "d";
}
</programlisting>
This is useful, for instance, in NixOS configuration files.</para>
</listitem>
<listitem>
<para>Support for Nix channels generated by Hydra, the Nix-based
continuous build system. (Hydra generates NAR archives on the
fly, so the size and hash of these archives isnt known in
advance.)</para>
</listitem>
<listitem>
<para>Support <literal>i686-linux</literal> builds directly on
<literal>x86_64-linux</literal> Nix installations. This is
implemented using the <function>personality()</function> syscall,
which causes <command>uname</command> to return
<literal>i686</literal> in child processes.</para>
</listitem>
<listitem>
<para>Various improvements to the <literal>chroot</literal>
support. Building in a <literal>chroot</literal> works quite well
now.</para>
</listitem>
<listitem>
<para>Nix no longer blocks if it tries to build a path and another
process is already building the same path. Instead it tries to
build another buildable path first. This improves
parallelism.</para>
</listitem>
<listitem>
<para>Support for large (> 4 GiB) files in NAR archives.</para>
</listitem>
<listitem>
<para>Various (performance) improvements to the remote build
mechanism.</para>
</listitem>
<listitem>
<para>New primops: <varname>builtins.addErrorContext</varname> (to
add a string to stack traces — useful for debugging),
<varname>builtins.isBool</varname>,
<varname>builtins.isString</varname>,
<varname>builtins.isInt</varname>,
<varname>builtins.intersectAttrs</varname>.</para>
</listitem>
<listitem>
<para>OpenSolaris support (Sander van der Burg).</para>
</listitem>
<listitem>
<para>Stack traces are no longer displayed unless the
<option>--show-trace</option> option is used.</para>
</listitem>
<listitem>
<para>The scoping rules for <literal>inherit
(<replaceable>e</replaceable>) ...</literal> in recursive
attribute sets have changed. The expression
<replaceable>e</replaceable> can now refer to the attributes
defined in the containing set.</para>
</listitem>
</itemizedlist>
</section>
<!--==================================================================-->
<section xml:id="ssec-relnotes-0.12"><title>Release 0.12 (November 20,
2008)</title>
<itemizedlist>
<listitem>
<para>Nix no longer uses Berkeley DB to store Nix store metadata.
The principal advantages of the new storage scheme are: it works
properly over decent implementations of NFS (allowing Nix stores
to be shared between multiple machines); no recovery is needed
when a Nix process crashes; no write access is needed for
read-only operations; no more running out of Berkeley DB locks on
certain operations.</para>
<para>You still need to compile Nix with Berkeley DB support if
you want Nix to automatically convert your old Nix store to the
new schema. If you dont need this, you can build Nix with the
<filename>configure</filename> option
<option>--disable-old-db-compat</option>.</para>
<para>After the automatic conversion to the new schema, you can
delete the old Berkeley DB files:
<screen>
$ cd /nix/var/nix/db
$ rm __db* log.* derivers references referrers reserved validpaths DB_CONFIG</screen>
The new metadata is stored in the directories
<filename>/nix/var/nix/db/info</filename> and
<filename>/nix/var/nix/db/referrer</filename>. Though the
metadata is stored in human-readable plain-text files, they are
not intended to be human-editable, as Nix is rather strict about
the format.</para>
<para>The new storage schema may or may not require less disk
space than the Berkeley DB environment, mostly depending on the
cluster size of your file system. With 1 KiB clusters (which
seems to be the <literal>ext3</literal> default nowadays) it
usually takes up much less space.</para>
</listitem>
<listitem><para>There is a new substituter that copies paths
directly from other (remote) Nix stores mounted somewhere in the
filesystem. For instance, you can speed up an installation by
mounting some remote Nix store that already has the packages in
question via NFS or <literal>sshfs</literal>. The environment
variable <envar>NIX_OTHER_STORES</envar> specifies the locations of
the remote Nix directories,
e.g. <literal>/mnt/remote-fs/nix</literal>.</para></listitem>
<listitem><para>New <command>nix-store</command> operations
<option>--dump-db</option> and <option>--load-db</option> to dump
and reload the Nix database.</para></listitem>
<listitem><para>The garbage collector has a number of new options to
allow only some of the garbage to be deleted. The option
<option>--max-freed <replaceable>N</replaceable></option> tells the
collector to stop after at least <replaceable>N</replaceable> bytes
have been deleted. The option <option>--max-links
<replaceable>N</replaceable></option> tells it to stop after the
link count on <filename>/nix/store</filename> has dropped below
<replaceable>N</replaceable>. This is useful for very large Nix
stores on filesystems with a 32000 subdirectories limit (like
<literal>ext3</literal>). The option <option>--use-atime</option>
causes store paths to be deleted in order of ascending last access
time. This allows non-recently used stuff to be deleted. The
option <option>--max-atime <replaceable>time</replaceable></option>
specifies an upper limit to the last accessed time of paths that may
be deleted. For instance,
<screen>
$ nix-store --gc -v --max-atime $(date +%s -d "2 months ago")</screen>
deletes everything that hasnt been accessed in two months.</para></listitem>
<listitem><para><command>nix-env</command> now uses optimistic
profile locking when performing an operation like installing or
upgrading, instead of setting an exclusive lock on the profile.
This allows multiple <command>nix-env -i / -u / -e</command>
operations on the same profile in parallel. If a
<command>nix-env</command> operation sees at the end that the profile
was changed in the meantime by another process, it will just
restart. This is generally cheap because the build results are
still in the Nix store.</para></listitem>
<listitem><para>The option <option>--dry-run</option> is now
supported by <command>nix-store -r</command> and
<command>nix-build</command>.</para></listitem>
<listitem><para>The information previously shown by
<option>--dry-run</option> (i.e., which derivations will be built
and which paths will be substituted) is now always shown by
<command>nix-env</command>, <command>nix-store -r</command> and
<command>nix-build</command>. The total download size of
substitutable paths is now also shown. For instance, a build will
show something like
<screen>
the following derivations will be built:
/nix/store/129sbxnk5n466zg6r1qmq1xjv9zymyy7-activate-configuration.sh.drv
/nix/store/7mzy971rdm8l566ch8hgxaf89x7lr7ik-upstart-jobs.drv
...
the following paths will be downloaded/copied (30.02 MiB):
/nix/store/4m8pvgy2dcjgppf5b4cj5l6wyshjhalj-samba-3.2.4
/nix/store/7h1kwcj29ip8vk26rhmx6bfjraxp0g4l-libunwind-0.98.6
...</screen>
</para></listitem>
<listitem><para>Language features:
<itemizedlist>
<listitem><para>@-patterns as in Haskell. For instance, in a
function definition
<programlisting>f = args @ {x, y, z}: <replaceable>...</replaceable>;</programlisting>
<varname>args</varname> refers to the argument as a whole, which
is further pattern-matched against the attribute set pattern
<literal>{x, y, z}</literal>.</para></listitem>
<listitem><para><literal>...</literal>” (ellipsis) patterns.
An attribute set pattern can now say <literal>...</literal> at
the end of the attribute name list to specify that the function
takes <emphasis>at least</emphasis> the listed attributes, while
ignoring additional attributes. For instance,
<programlisting>{stdenv, fetchurl, fuse, ...}: <replaceable>...</replaceable></programlisting>
defines a function that accepts any attribute set that includes
at least the three listed attributes.</para></listitem>
<listitem><para>New primops:
<varname>builtins.parseDrvName</varname> (split a package name
string like <literal>"nix-0.12pre12876"</literal> into its name
and version components, e.g. <literal>"nix"</literal> and
<literal>"0.12pre12876"</literal>),
<varname>builtins.compareVersions</varname> (compare two version
strings using the same algorithm that <command>nix-env</command>
uses), <varname>builtins.length</varname> (efficiently compute
the length of a list), <varname>builtins.mul</varname> (integer
multiplication), <varname>builtins.div</varname> (integer
division).
<!-- <varname>builtins.genericClosure</varname> -->
</para></listitem>
</itemizedlist>
</para></listitem>
<listitem><para><command>nix-prefetch-url</command> now supports
<literal>mirror://</literal> URLs, provided that the environment
variable <envar>NIXPKGS_ALL</envar> points at a Nixpkgs
tree.</para></listitem>
<listitem><para>Removed the commands
<command>nix-pack-closure</command> and
<command>nix-unpack-closure</command>. You can do almost the same
thing but much more efficiently by doing <literal>nix-store --export
$(nix-store -qR <replaceable>paths</replaceable>) > closure</literal> and
<literal>nix-store --import &lt;
closure</literal>.</para></listitem>
<listitem><para>Lots of bug fixes, including a big performance bug in
the handling of <literal>with</literal>-expressions.</para></listitem>
<listitem><para><command>nix-store --dump-db / --load-db</command>.</para></listitem>
</itemizedlist>

View File

@@ -5,10 +5,121 @@
<para>This section provides solutions for some common problems. See
the <link xlink:href="http://bugs.strategoxt.org/browse/NIX">Nix
the <link xlink:href="https://bugs.cs.uu.nl/browse/NIX">Nix
bug tracker</link> for a list of currently known issues.</para>
<section><title>Berkeley DB: <quote>Cannot allocate memory</quote></title>
<para>Symptom: Nix operations (in particular the
<command>nix-store</command> operations <option>--gc</option>,
<option>--verify</option>, and <option>--clear-substitutes</option>
the latter being called by <command>nix-channel --update</command>)
failing:
<screen>
$ nix-store --verify
error: Db::del: Cannot allocate memory</screen>
</para>
<para>Possible solution: make sure that no Nix processes are running,
then do:
<screen>
$ cd /nix/var/nix/db
$ rm __db.00*</screen>
</para>
</section>
<section><title>Berkeley DB gives weird error messages</title>
<para>Symptom: you get error messages such as
<screen>
Berkeley DB message: Finding last valid log LSN: file: 1 offset 28
Berkeley DB error: file validpaths (meta pgno = 0) has LSN [483][34721].
Berkeley DB error: end of log is [1][28]
Berkeley DB error: /nix/var/nix/db/validpaths: unexpected file type or format</screen>
or other weird Berkeley DB errors, and they dont go away (i.e.,
automatic recovery doesnt work). This may be the case after a system
crash.</para>
<para>Solution: first try to run <command>db_recover</command> and
then <link linkend='refsec-nix-store-verify'><command>nix-store
--verify</command></link>:
<screen>
$ db_recover -h /nix/var/nix/db
$ nix-store --verify</screen>
(Make sure that you have the right version of
<command>db_recover</command>, namely, Berkeley DB 4.4 for Nix 0.10,
and 4.5 for Nix 0.11.)</para>
<para>If that doesnt work, its time to bring out the big guns:
<screen>
$ cd /nix/var/nix
$ cp -pr db db-backup <lineannotation>(making a backup just in case)</lineannotation>
$ cd db
$ rm __db.* log* <lineannotation>(removing the Berkeley DB environment)</lineannotation>
$ mkdir tmp
$ for i in *; do db_dump $i | (cd tmp &amp;&amp; db_load $i); done
<lineannotation>(ignore error messages about non-database files like “reserved”)</lineannotation>
$ mv tmp/* .
$ nix-store --verify</screen>
</para>
</section>
<section><title>Berkeley DB out of locks</title>
<para>It is possible, especially in <command>nix-store
--verify</command> or when running the garbage collector, to run out
of Berkeley DB locks, like this:
<screen>
$ 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</screen>
</para>
<para>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
<filename>/nix/var/nix/db/<link
xlink:href="http://www.oracle.com/technology/documentation/berkeley-db/db/ref/env/db_config.html">DB_CONFIG</link></filename>:
<programlisting>
set_lk_max_locks 100000
set_lk_max_lockers 100000
set_lk_max_objects 100000
</programlisting>
(Increase these numbers if necessary.) Then make sure that there are
no running Nix processes and delete the Berkeley DB environment:
<screen>
$ rm /nix/var/nix/db/__db.*</screen>
The Berkeley DB environment is automatically recreated with the new
limits when you run any Nix command.</para>
</section>
<section><title>Collisions in <command>nix-env</command></title>
<para>Symptom: when installing or upgrading, you get an error message such as
@@ -76,8 +187,7 @@ Furthermore, the <literal>st_nlink</literal> field of the
<para>This only happens on very large Nix installations (such as build
machines).</para>
<para>Quick solution: run the garbage collector. You may want to use
the <option>--max-links</option> option.</para>
<para>Quick solution: run the garbage collector.</para>
<para>Real solution: put the Nix store on a file system that supports
more than 32,000 subdirectories per directory, such as ReiserFS.

View File

@@ -731,9 +731,9 @@ stdenv.mkDerivation {
xlink:href='http://www.ietf.org/rfc/rfc2396.txt'>RFC 2396</link>
can be written <emphasis>as is</emphasis>, without quotes. For
instance, the string
<literal>"http://example.org/foo.tar.bz2"</literal>
<literal>"https://svn.cs.uu.nl:12443/dist/trace/trace-nix-trunk.tar.bz2"</literal>
can also be written as
<literal>http://example.org/foo.tar.bz2</literal>.</para>
<literal>https://svn.cs.uu.nl:12443/dist/trace/trace-nix-trunk.tar.bz2</literal>.</para>
</listitem>
@@ -937,84 +937,17 @@ set.</para>
<para>Functions have the following form:
<programlisting>
<replaceable>pattern</replaceable>: <replaceable>body</replaceable></programlisting>
{<replaceable>params</replaceable>}: <replaceable>body</replaceable></programlisting>
The pattern specifies what the argument of the function must look
like, and binds variables in the body to (parts of) the
argument. There are three kinds of patterns:</para>
<itemizedlist>
<listitem><para>If a pattern is a single identifier, then the
function matches any argument. Example:
<programlisting>
let negate = x: !x;
concat = x: y: x + y;
in if negate true then concat "foo" "bar" else ""</programlisting>
Note that <function>concat</function> is a function that takes one
argument and returns a function that takes another argument. This
allows partial parameterisation (i.e., only filling some of the
arguments of a function); e.g.,
<programlisting>
map (concat "foo") ["bar" "bla" "abc"]</programlisting>
evaluates to <literal>["foobar" "foobla"
"fooabc"]</literal>.</para></listitem>
<listitem><para>An <emphasis>attribute set pattern</emphasis> of the
form <literal>{name1, name2, …, nameN}</literal>
matches an attribute set containing the listed attributes, and binds
the values of those attributes to variables in the function body.
For example, the function
<programlisting>
{x, y, z}: z + y + x</programlisting>
can only be called with a set containing exactly the attributes
<varname>x</varname>, <varname>y</varname> and
<varname>z</varname>. No other attributes are allowed. If you want
to allow additional arguments, you can use an ellipsis
(<literal>...</literal>):
<programlisting>
{x, y, z, ....}: z + y + x</programlisting>
This works on any set that contains at least the three named
attributes.</para>
<para>It is possible to provide <emphasis>default values</emphasis>
for attributes, in which case they are allowed to be missing. A
default value is specified by writing
<literal><replaceable>name</replaceable> ?
<replaceable>e</replaceable></literal>, where
<replaceable>e</replaceable> is an arbitrary expression. For example,
<programlisting>
{x, y ? "foo", z ? "bar"}: z + y + x</programlisting>
specifies a function that only requires an attribute named
<varname>x</varname>, but optionally accepts <varname>y</varname>
and <varname>z</varname>.</para></listitem>
<listitem><para>An <literal>@</literal>-pattern requires that the
argument matches with the patterns on the left- and right-hand side
of the <literal>@</literal>-sign. For example:
<programlisting>
args@{x, y, z, ...}: z + y + x + args.a</programlisting>
Here <varname>args</varname> is bound to the entire argument, which
is further matches against the pattern <literal>{x, y, z,
...}</literal>.</para></listitem>
</itemizedlist>
This defines a function that must be called with an attribute set
containing the attributes listed in <replaceable>params</replaceable>,
which is a comma-separated list of attribute names. Optionally, for
each parameter a <emphasis>default value</emphasis> may be specified
by writing <literal><replaceable>param</replaceable> ?
<replaceable>e</replaceable></literal>, where
<replaceable>e</replaceable> is an arbitrary expression. If a
parameter has a default, the corresponding attribute may be omitted in
function calls.</para>
<para>Note that functions do not have names. If you want to give them
a name, you can bind them to an attribute, e.g.,
@@ -1025,6 +958,31 @@ in concat {x = "foo"; y = "bar";}</programlisting>
</para>
<para>It is also possible to define a function that takes a single
argument and that does not need to be called with an attribute set as
argument. The syntax is
<programlisting>
<replaceable>var</replaceable>: <replaceable>body</replaceable></programlisting>
where <replaceable>var</replaceable> is the name of the argument. It
is not possible to define a default. Example:
<programlisting>
let negate = x: !x;
concat = x: y: x + y;
in if negate true then concat "foo" "bar" else ""</programlisting>
Note that <function>concat</function> is a function that takes one
arguments and returns a function that takes another argument. This
allows partial parameterisation (i.e., only filling some of the
arguments of a function); e.g.,
<programlisting>
map (concat "foo") ["bar" "bla" "abc"]</programlisting>
evaluates to <literal>["foobar" "foobla" "fooabc"]</literal>.</para>
</simplesect>
@@ -1106,7 +1064,7 @@ used in the Nix expression for Subversion.</para>
incompatibility might occur.</para>
</callout>
<callout arearefs='ex-subversion-nix-co-3'>
<callout arearefs='ex-subversion-nix-co-2'>
<para>This assertion says that in order for Subversion to have SSL
support (so that it can access <literal>https</literal> URLs), an
OpenSSL library must be passed. Additionally, it says that
@@ -1432,7 +1390,7 @@ command-line argument. See <xref linkend='sec-standard-environment'
inputs.</para></listitem>
<listitem><para>After the build, Nix sets the last-modified
timestamp on all files in the build result to 1 (00:00:01 1/1/1970
timestamp on all files in the build result to 0 (00:00:00 1/1/1970
UTC), sets the group to the default group, and sets the mode of the
file to 0444 or 0555 (i.e., read-only, with execute permission
enabled if the file was originally executable). Note that possible
@@ -1686,6 +1644,59 @@ impureEnvVars = ["http_proxy" "https_proxy" <replaceable>...</replaceable>];
<section xml:id='sec-standard-environment'><title>The standard environment</title>
<para>The standard build environment in the Nix Packages collection
provides a basic environment for building Unix packages. It consists
of the following packages:
<itemizedlist>
<listitem><para>The GNU C Compiler, configured with C and C++
support. On Linux, the compiler has been patched to provide greater
<quote>purity</quote> assurance. For instance, the compiler doesn't
search in locations such as <filename>/usr/include</filename>. In
fact, attempts to add such directories through the
<option>-I</option> flag are filtered out. Likewise, the linker
(from GNU binutils) doesn't search in standard locations such as
<filename>/usr/lib</filename>. Programs built on Linux are linked
against a GNU C Library that likewise doesn't search in the default
system locations.</para></listitem>
<listitem><para>GNU coreutils (contains a few dozen standard Unix
commands).</para></listitem>
<listitem><para>GNU findutils (contains
<command>find</command>).</para></listitem>
<listitem><para>GNU diffutils (contains <command>diff</command>,
<command>cmp</command>).</para></listitem>
<listitem><para>GNU <command>sed</command>.</para></listitem>
<listitem><para>GNU <command>grep</command>.</para></listitem>
<listitem><para>GNU <command>awk</command>.</para></listitem>
<listitem><para>GNU <command>tar</command>.</para></listitem>
<listitem><para><command>gzip</command> and
<command>bzip2</command>.</para></listitem>
<listitem><para>GNU Make. It has been patched to provide
<quote>nested</quote> output that can be fed into the
<command>nix-log2xml</command> command and
<command>log2html</command> stylesheet to create a structured,
readable output of the build steps performed by
Make.</para></listitem>
<listitem><para>Bash. This is the shell used for all builders in
the Nix Packages collection. Not using <command>/bin/sh</command>
removes a large source of portability problems.</para></listitem>
<listitem><para>Patch.</para></listitem>
</itemizedlist>
</para>
<para>The standard environment is used by passing it as an input
called <envar>stdenv</envar> to the derivation, and then doing
@@ -1754,6 +1765,115 @@ myPostInstall() {
</para>
<para>The generic builder has a number of <emphasis>phases</emphasis>,
each of which can be override in its entirety by setting the indicated
variable. The phases are:
<itemizedlist>
<listitem>
<para><function>unpackPhase</function> unpacks the source files
listed in the <envar>src</envar> environment variable to the
current directory. It supports <filename>tar</filename> files,
optionally compressed with <command>gzip</command> or
<command>bzip2</command>; Zip files (but note that the
<command>unzip</command> command is not a part of the standard
environment; you should add it as a build input yourself); and
unpacked source trees (i.e., directories; they are copied
verbatim). You can add support for other file types by setting
the <varname>findUnpacker</varname> hook. This hook should set
the variable <varname>unpackCmd</varname> to contain the command
to be executed to unpack the file.</para>
<para>After unpacking all source files,
<function>unpackPhase</function> changes the current directory to
the directory created by unpacking the sources. If there are
multiple source directories, you should set
<varname>sourceRoot</varname> to the name of the intended
directory.</para>
<para>It also calls the hook <varname>postUnpack</varname> after
unpacking.</para>
</listitem>
<listitem><para><function>patchPhase</function> calls the
<command>patch</command> command with the <option>-p1</option>
option for each patch file listed in the <envar>patches</envar>
variable.</para></listitem>
<listitem>
<para><function>configurePhase</function> runs the script called
<filename>configure</filename> in the current directory with a
<option>--prefix</option> set to the output path. You can add
additional flags through the <varname>configureFlags</varname>
variable. If <filename>configure</filename> does not exist,
nothing happens.</para>
<para>Before and after running <filename>configure</filename>, the
hooks <varname>preConfigure</varname> and
<varname>postConfigure</varname> are called, respectively.</para>
</listitem>
<listitem>
<para><function>buildPhase</function> calls
<command>make</command>. You can set flags for
<command>make</command> through the <varname>makeFlags</varname>
variable.</para>
<para>Before and after running <command>make</command>, the hooks
<varname>preBuild</varname> and <varname>postBuild</varname> are
called, respectively.</para>
</listitem>
<listitem><para><function>checkPhase</function> calls <command>make
check</command>, but only if the <varname>doCheck</varname> variable
is set to <literal>1</literal>. Additional flags can be set through
the <varname>checkFlags</varname> variable.</para></listitem>
<listitem>
<para><function>installPhase</function> calls <command>make
install</command>. Additional flags can be set through the
<varname>installFlags</varname> variable. It also strips any
static libraries in the output path of debug information unless
<varname>dontStrip</varname> is set to
<literal>1</literal>.</para>
<para>Before and after running <command>make install</command>,
the hooks <varname>preInstall</varname> and
<varname>postInstall</varname> are called, respectively.</para>
</listitem>
<listitem>
<para><function>distPhase</function> calls <command>make
dist</command>, but only if the <varname>doDist</varname> variable
is set to <literal>1</literal>. Additional flags can be set
through the <varname>distFlags</varname> variable. The resulting
tarball is copied to the <filename>/tarballs</filename>
subdirectory of the output path.</para>
<para>Before and after running <command>make dist</command>, the
hooks <varname>preDist</varname> and <varname>postDist</varname>
are called, respectively.</para>
</listitem>
</itemizedlist>
</para>
<para>You can change the order in which phases are executed, or add
new phases, by setting the <varname>phases</varname> variable. The
default is <literal>patchPhase configurePhase buildPhase checkPhase
installPhase distPhase</literal>.</para>
</section>

52
externals/Makefile.am vendored
View File

@@ -1,3 +1,38 @@
# Berkeley DB
DB = db-4.5.20
$(DB).tar.gz:
@echo "Nix requires Berkeley DB to build."
@echo "Please download version 4.5.20 from"
@echo " http://download-east.oracle.com/berkeley-db/db-4.5.20.tar.gz"
@echo "and place it in the externals/ directory."
false
$(DB): $(DB).tar.gz
gunzip < $(srcdir)/$(DB).tar.gz | tar xvf -
(cd $(DB) && $(patch) -p1) < $(srcdir)/bdb-cygwin.patch
have-db:
$(MAKE) $(DB)
touch have-db
if HAVE_BDB
build-db:
else
build-db: have-db
(pfx=`pwd` && \
cd $(DB)/build_unix && \
CC="$(CC)" CXX="$(CXX)" CFLAGS="$(CFLAGS)" CXXFLAGS="$(CXXFLAGS)" \
../dist/configure --prefix=$$pfx/inst-bdb \
--enable-cxx --disable-shared --disable-cryptography \
--disable-replication --disable-verify && \
$(MAKE) && \
$(MAKE) install_include install_lib)
touch build-db
endif
# CWI ATerm
ATERM = aterm-2.4.2-fixes-r2
@@ -5,7 +40,7 @@ ATERM = aterm-2.4.2-fixes-r2
$(ATERM).tar.bz2:
@echo "Nix requires the CWI ATerm library to build."
@echo "Please download version 2.4.2-fixes-r2 from"
@echo " http://nixos.org/tarballs/aterm-2.4.2-fixes-r2.tar.bz2"
@echo " http://losser.st-lab.cs.uu.nl/~eelco/dist/aterm-2.4.2-fixes-r2.tar.bz2"
@echo "and place it in the externals/ directory."
false
@@ -32,12 +67,12 @@ endif
# bzip2
BZIP2 = bzip2-1.0.5
BZIP2 = bzip2-1.0.4
$(BZIP2).tar.gz:
@echo "Nix requires bzip2 to build."
@echo "Please download version 1.0.5 from"
@echo " http://www.bzip.org/1.0.5/bzip2-1.0.5.tar.gz"
@echo "Please download version 1.0.4 from"
@echo " http://www.bzip.org/1.0.4/bzip2-1.0.4.tar.gz"
@echo "and place it in the externals/ directory."
false
@@ -64,10 +99,11 @@ install:
endif
all: build-aterm build-bzip2
all: build-db build-aterm build-bzip2
EXTRA_DIST = $(ATERM).tar.bz2 $(BZIP2).tar.gz
EXTRA_DIST = $(DB).tar.gz $(ATERM).tar.bz2 $(BZIP2).tar.gz \
bdb-cygwin.patch
ext-clean:
$(RM) -f have-aterm build-aterm have-bzip2 build-bzip2
$(RM) -rf $(ATERM) $(BZIP2)
$(RM) -f have-db build-db have-aterm build-aterm
$(RM) -rf $(DB) $(ATERM) $(BZIP2)

22
externals/bdb-cygwin.patch vendored Normal file
View File

@@ -0,0 +1,22 @@
diff -rc db-4.5.20-orig/os/os_flock.c db-4.5.20/os/os_flock.c
*** db-4.5.20-orig/os/os_flock.c 2006-10-13 12:36:12.000000000 +0200
--- db-4.5.20/os/os_flock.c 2006-10-13 12:40:11.000000000 +0200
***************
*** 30,35 ****
--- 30,44 ----
DB_ASSERT(dbenv, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1);
+ #ifdef __CYGWIN__
+ /*
+ * Windows file locking interferes with read/write operations, so we
+ * map the ranges to an area past the end of the file.
+ */
+ DB_ASSERT(dbenv, offset < (off_t) 1 << 62);
+ offset += (off_t) 1 << 62;
+ #endif
+
fl.l_start = offset;
fl.l_len = 1;
fl.l_type = acquire ? F_WRLCK : F_UNLCK;
Only in db-4.5.20/os: os_flock.c~

67
install_full.sh Executable file
View File

@@ -0,0 +1,67 @@
#! /bin/sh -e
make clean # comment this out when needed !!!
export nixstatepath=/nixstate2/nix
export ACLOCAL_PATH=/home/wouterdb/.nix-profile/share/aclocal
if [ "$1" = "full" ]; then
nix-env-all-pkgs.sh -i gcc
nix-env-all-pkgs.sh -i gnum4
nix-env-all-pkgs.sh -i autoconf
nix-env-all-pkgs.sh -i automake
nix-env-all-pkgs.sh -i gnused
nix-env-all-pkgs.sh -i db4
nix-env-all-pkgs.sh -i aterm
nix-env-all-pkgs.sh -i bzip2
nix-env-all-pkgs.sh -i flex
nix-env-all-pkgs.sh -i bsdiff
nix-env-all-pkgs.sh -i libtool
nix-env-all-pkgs.sh -i docbook5
nix-env-all-pkgs.sh -i docbook5-xsl
nix-env-all-pkgs.sh -i bison
nix-env-all-pkgs.sh -i gdb #optional for debugging
nix-env-all-pkgs.sh -i gnupatch
nix-env-all-pkgs.sh -i gnumake
nix-env-all-pkgs.sh -i ext3cow-tools
nix-env-all-pkgs.sh -i e3cfsprogs
nix-env-all-pkgs.sh -i rsync
fi
if [ "$1" = "full" ] || [ "$1" = "auto" ]; then
export AUTOCONF=autoconf
export AUTOHEADER=autoheader
export AUTOMAKE=automake
autoconf
autoreconf -f
aclocal
autoheader
automake
fi
./bootstrap.sh
./configure --with-aterm=$HOME/.nix-profile \
--with-bzip2=$HOME/.nix-profile \
--with-bdb=$HOME/.nix-profile \
--with-docbook-xsl=$HOME/.nix-profile \
--with-docbook-rng=/home/wouterdb/.nix-profile/xml/rng/docbook \
--with-docbook-xsl=/home/wouterdb/.nix-profile/xml/xsl/docbook \
--prefix=$nixstatepath \
--with-store-dir=/nix/store \
--with-store-state-dir=/nix/state \
--with-ext3cow-header=/nix/store/2sm0h2xd1zsm5had53q1pvzmnsn8fy8k-linux-2.6.21/lib/modules/2.6.21-ck1-default/build/include/linux/ext3cow_fs.h \
--localstatedir=/nix/var
#Options from the nix expr
#--disable-init-state
#--with-store-dir=/nix/store
#--localstatedir=/nix/var
#--with-aterm=/nix/store/pkmzbb613wa8cwngx8jjb5jaic8yhyzs-aterm-2.4.2-fixes
#--with-bdb=/nix/store/4yv4j1cd7i5j3mhs5wpc1kzlz1cj8n82-db4-4.5.20
#--with-bzip2=/nix/store/dh0mdgkvhv3pwrf8zp58phpzn9rcm49r-bzip2-1.0.3
#--disable-init-state
echo "New state nix version by wouter ..." > doc/manual/NEWS.txt
make

16
install_install_d.sh Executable file
View File

@@ -0,0 +1,16 @@
#! /bin/sh -e
if [ $(whoami) = "root" ]
then
su - wouterdb -c "cd /home/wouterdb/dev/nix-state/; make"
make install
chown -R wouterdb.wouterdb /nixstate2/nix/
./restartDaemon.sh
else
echo "You must be ROOT to run this script."
exit 0
fi

5
install_make.sh Executable file
View File

@@ -0,0 +1,5 @@
#! /bin/sh -e
make

36
mergeTrunkBackIn.sh Executable file
View File

@@ -0,0 +1,36 @@
svn merge -r 10855:10943 https://svn.cs.uu.nl:12443/repos/trace/nix/trunk
#already done:
# 8628
# 8632
# 8634
# 8636
# 8655
# 8691
# 8698
# 8711
# 8864
# 9063
# 9105
# 9207
# 9217
# 9332
# 9429
# 9433
# 9435
# 9437
# 9439
# 9445
# 9476
# 9506
# 9536
# 9549
# 9561
# 9584
# 9751
# 10133
# 10154
# 10531
# 10692
# 10855
# 10943

View File

@@ -76,10 +76,10 @@ The hook `nix-mode-hook' is run when Nix mode is started.
("\\<baseNameOf\\>" . font-lock-builtin-face)
("\\<toString\\>" . font-lock-builtin-face)
("\\<isNull\\>" . font-lock-builtin-face)
("\\<\\([a-zA-Z_][a-zA-Z0-9_']*\\)[ \t]*="
(1 font-lock-variable-name-face nil nil))
("[a-zA-Z][a-zA-Z0-9\\+-\\.]*:[a-zA-Z0-9%/\\?:@&=\\+\\$,_\\.!~\\*'-]+"
. font-lock-constant-face)
("\\<\\([a-zA-Z_][a-zA-Z0-9_'\.]*\\)[ \t]*="
(1 font-lock-variable-name-face nil nil))
("[a-zA-Z0-9._\\+-]*\\(/[a-zA-Z0-9._\\+-]+\\)+"
. font-lock-constant-face)
))

View File

@@ -21,14 +21,12 @@ syn match nixFuncArg "\zs\w\+\ze\s*:"
syn region nixStringParam start=+\${+ end=+}+
syn region nixMultiLineComment start=+/\*+ skip=+\\"+ end=+\*/+
syn match nixEndOfLineComment "#.*$"
syn region nixStringIndented start=+''+ skip=+'''\|''${\|"+ end=+''+ contains=nixStringParam
syn region nixString start=+"+ skip=+\\"+ end=+"+ contains=nixStringParam
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 nixStringIndented String
hi def link nixBuiltin Special
hi def link nixStringParam Macro
hi def link nixMultiLineComment Comment

View File

@@ -29,6 +29,25 @@
#gc-keep-derivations = true
### Option `gc-reserved-space'
#
# This option specifies how much space should be reserved in normal
# use so that the garbage collector can run succesfully. Since the
# garbage collector must perform Berkeley DB transactions, it needs
# some disk space for itself. However, when the disk is full, this
# space is not available, so the collector would not be able to run
# precisely when it is most needed.
#
# For this reason, when Nix is run, it allocates a file
# /nix/var/nix/db/reserved of the size specified by this option. When
# the garbage collector is run, this file is deleted before the
# Berkeley DB environment is opened. This should give it enough room
# to proceed.
#
# The default is "1048576" (1 MiB).
#gc-reserved-space = 1048576
### Option `env-keep-derivations'
#
# If `false' (default), derivations are not stored in Nix user
@@ -145,26 +164,30 @@
# (using `mount --bind' on Linux) some directories from the normal
# file system hierarchy inside the chroot. These are the Nix store,
# the temporary build directory (usually /tmp/nix-<pid>-<number>) and
# the directories listed here. The default is "/dev /dev/pts /proc".
# Files in /dev (such as /dev/null) are needed by many builds, and
# some files in /proc may also be needed occasionally.
# the directories listed here. The default is "/dev /proc". Files
# in /dev (such as /dev/null) are needed by many builds, and some
# files in /proc may also be needed occasionally.
#
# Example:
# build-use-chroot = /dev /proc /bin
#build-chroot-dirs = /dev /dev/pts /proc
#build-chroot-dirs = /dev /proc
### Option `build-cache-failure'
### Option `system'
#
# If this option is enabled, Nix will do negative caching; that is, it
# will remember failed builds, and won't attempt to try to build them
# again if you ask for it. Negative caching is disabled by default
# because Nix cannot distinguish between permanent build errors (e.g.,
# a syntax error in a source file) and transient build errors (e.g., a
# full disk), as they both cause the builder to return a non-zero exit
# code. You can clear the cache by doing `rm -f
# /nix/var/nix/db/failed/*'.
# This option specifies the canonical Nix system name of the current
# installation, such as `i686-linux' or `powerpc-darwin'. Nix can
# only build derivations whose `system' attribute equals the value
# specified here. In general, it never makes sense to modify this
# value from its default, since you can use it to `lie' about the
# platform you are building on (e.g., perform a Mac OS build on a
# Linux machine; the result would obviously be wrong). It only makes
# sense if the Nix binaries can run on multiple platforms, e.g.,
# `universal binaries' that run on `powerpc-darwin' and `i686-darwin'.
#
# It defaults to the canonical Nix system name detected by `configure'
# at build time.
#
# Example:
# build-cache-failure = true
#build-cache-failure = false
# system = i686-darwin
#system =

View File

@@ -13,10 +13,11 @@ Version: @version@
Release: 1
License: GPL
Group: Software Deployment
URL: http://nixos.org/
URL: http://nix.cs.uu.nl/
Source0: %{name}-@version@.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
Prefix: /usr
%define _prefix /nix
Prefix: %{_prefix}
Requires: /usr/bin/perl
Requires: curl
@@ -46,14 +47,14 @@ if test -n "%{enable_setuid}"; then
extraFlags="$extraFlags --with-nix-group=%{nix_group}"
fi
fi
./configure --prefix=%{_prefix} --sysconfdir=/etc $extraFlags
./configure --prefix=%{_prefix} $extraFlags
make
make check
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
rm $RPM_BUILD_ROOT/etc/nix/nix.conf
rm $RPM_BUILD_ROOT/%{_prefix}/etc/nix/nix.conf
strip $RPM_BUILD_ROOT/%{_prefix}/bin/* || true
%clean
@@ -75,9 +76,10 @@ fi
%{_prefix}/lib
%{_prefix}/libexec
%{_prefix}/include
%{_prefix}/var
%{_prefix}/share
/etc/profile.d/nix.sh
/nix/var
/nix/store
%{_prefix}/store
%config
/etc/nix
%{_prefix}/etc
#%doc
#%{_prefix}/share/nix/manual

View File

@@ -1,209 +0,0 @@
{ nixpkgs ? ../nixpkgs }:
let
jobs = rec {
tarball =
{ nix ? {outPath = ./.; rev = 1234;}
, officialRelease ? false
}:
with import nixpkgs {};
releaseTools.sourceTarball {
name = "nix-tarball";
version = builtins.readFile ./version;
src = nix;
inherit officialRelease;
buildInputs =
[ curl bison flex2533 perl libxml2 libxslt w3m bzip2
tetex dblatex nukeReferences
];
configureFlags = ''
--with-docbook-rng=${docbook5}/xml/rng/docbook
--with-docbook-xsl=${docbook5_xsl}/xml/xsl/docbook
--with-xml-flags=--nonet
'';
# Include the ATerm and Bzip2 tarballs in the distribution.
preConfigure = ''
stripHash ${aterm242fixes.src}
cp -pv ${aterm242fixes.src} externals/$strippedName
stripHash ${bzip2.src}
cp -pv ${bzip2.src} externals/$strippedName
# TeX needs a writable font cache.
export VARTEXFONTS=$TMPDIR/texfonts
'';
preDist = ''
make -C doc/manual install prefix=$out
make -C doc/manual manual.pdf prefix=$out
cp doc/manual/manual.pdf $out/manual.pdf
# The PDF containes filenames of included graphics (see
# http://www.tug.org/pipermail/pdftex/2007-August/007290.html).
# This causes a retained dependency on dblatex, which Hydra
# doesn't like (the output of the tarball job is distributed
# to Windows and Macs, so there should be no Linux binaries
# in the closure).
nuke-refs $out/manual.pdf
echo "doc manual $out/share/doc/nix/manual" >> $out/nix-support/hydra-build-products
echo "doc-pdf manual $out/manual.pdf" >> $out/nix-support/hydra-build-products
echo "doc release-notes $out/share/doc/nix/release-notes" >> $out/nix-support/hydra-build-products
'';
};
build =
{ tarball ? jobs.tarball {}
, system ? "i686-linux"
}:
with import nixpkgs {inherit system;};
releaseTools.nixBuild {
name = "nix";
src = tarball;
buildInputs = [curl perl bzip2 openssl];
configureFlags = ''
--disable-init-state
--with-aterm=${aterm242fixes} --with-bzip2=${bzip2}
'';
};
/*
static =
{ tarball ? jobs.tarball {}
, system ? "i686-linux"
}:
with import nixpkgs {inherit system;};
releaseTools.binaryTarball {
name = "nix-static-tarball";
src = tarball;
buildInputs = [curl perl bzip2];
configureFlags = ''
--disable-init-state
--with-aterm=${aterm242fixes} --with-bzip2=${bzip2}
--enable-static-nix
'';
};
*/
coverage =
{ tarball ? jobs.tarball {}
}:
with import nixpkgs {};
releaseTools.coverageAnalysis {
name = "nix-build";
src = tarball;
buildInputs = [
curl perl bzip2 openssl
# These are for "make check" only:
graphviz libxml2 libxslt
];
configureFlags = ''
--disable-init-state --disable-shared
--with-aterm=${aterm242fixes} --with-bzip2=${bzip2}
'';
lcovFilter = ["*/boost/*" "*-tab.*"];
# We call `dot', and even though we just use it to
# syntax-check generated dot files, it still requires some
# fonts. So provide those.
FONTCONFIG_FILE = texFunctions.fontsConf;
};
rpm_fedora5i386 = makeRPM_i686 (diskImages: diskImages.fedora5i386) 10;
rpm_fedora9i386 = makeRPM_i686 (diskImages: diskImages.fedora9i386) 20;
rpm_fedora9x86_64 = makeRPM_x86_64 (diskImages: diskImages.fedora9x86_64) 20;
rpm_fedora10i386 = makeRPM_i686 (diskImages: diskImages.fedora10i386) 30;
rpm_fedora10x86_64 = makeRPM_x86_64 (diskImages: diskImages.fedora10x86_64) 30;
rpm_fedora11i386 = makeRPM_i686 (diskImages: diskImages.fedora11i386) 40;
rpm_fedora11x86_64 = makeRPM_x86_64 (diskImages: diskImages.fedora11x86_64) 40;
rpm_fedora12i386 = makeRPM_i686 (diskImages: diskImages.fedora12i386) 50;
rpm_fedora12x86_64 = makeRPM_x86_64 (diskImages: diskImages.fedora12x86_64) 50;
rpm_opensuse103i386 = makeRPM_i686 (diskImages: diskImages.opensuse103i386) 40;
rpm_opensuse110i386 = makeRPM_i686 (diskImages: diskImages.opensuse110i386) 50;
rpm_opensuse110x86_64 = makeRPM_x86_64 (diskImages: diskImages.opensuse110x86_64) 50;
deb_debian40i386 = makeDeb_i686 (diskImages: diskImages.debian40i386) 40;
deb_debian40x86_64 = makeDeb_x86_64 (diskImages: diskImages.debian40x86_64) 40;
deb_debian50i386 = makeDeb_i686 (diskImages: diskImages.debian50i386) 50;
deb_debian50x86_64 = makeDeb_x86_64 (diskImages: diskImages.debian50x86_64) 50;
deb_ubuntu804i386 = makeDeb_i686 (diskImages: diskImages.ubuntu804i386) 20;
deb_ubuntu804x86_64 = makeDeb_x86_64 (diskImages: diskImages.ubuntu804x86_64) 20;
deb_ubuntu810i386 = makeDeb_i686 (diskImages: diskImages.ubuntu810i386) 30;
deb_ubuntu810x86_64 = makeDeb_x86_64 (diskImages: diskImages.ubuntu810x86_64) 30;
deb_ubuntu904i386 = makeDeb_i686 (diskImages: diskImages.ubuntu904i386) 40;
deb_ubuntu904x86_64 = makeDeb_x86_64 (diskImages: diskImages.ubuntu904x86_64) 40;
deb_ubuntu910i386 = makeDeb_i686 (diskImages: diskImages.ubuntu910i386) 50;
deb_ubuntu910x86_64 = makeDeb_x86_64 (diskImages: diskImages.ubuntu910x86_64) 50;
};
makeRPM_i686 = makeRPM "i686-linux";
makeRPM_x86_64 = makeRPM "x86_64-linux";
makeRPM =
system: diskImageFun: prio:
{ tarball ? jobs.tarball {}
}:
with import nixpkgs {inherit system;};
releaseTools.rpmBuild rec {
name = "nix-rpm-${diskImage.name}";
src = tarball;
diskImage = diskImageFun vmTools.diskImages;
memSize = 1024;
meta = { schedulingPriority = toString prio; };
};
makeDeb_i686 = makeDeb "i686-linux";
makeDeb_x86_64 = makeDeb "x86_64-linux";
makeDeb =
system: diskImageFun: prio:
{ tarball ? jobs.tarball {}
}:
with import nixpkgs {inherit system;};
releaseTools.debBuild {
name = "nix-deb";
src = tarball;
diskImage = diskImageFun vmTools.diskImages;
memSize = 1024;
meta = { schedulingPriority = toString prio; };
configureFlags = "--sysconfdir=/etc";
debRequires = ["curl"];
};
in jobs

9
restartDaemon.sh Executable file
View File

@@ -0,0 +1,9 @@
#! /bin/sh
initctl stop nix-daemon
killproc.sh nix-worker
sleep 2
#/nixstate2/nix/bin/nix-worker --daemon > /dev/null 2>&1 &
/nixstate2/nix/bin/nix-worker --daemon
#gdb --args /nixstate2/nix/bin/nix-worker --daemon

View File

@@ -1,26 +1,24 @@
bin_SCRIPTS = nix-collect-garbage \
nix-pull nix-push nix-prefetch-url \
nix-install-package nix-channel nix-build \
nix-pack-closure nix-unpack-closure \
nix-copy-closure
noinst_SCRIPTS = nix-profile.sh generate-patches.pl \
find-runtime-roots.pl build-remote.pl nix-reduce-build \
copy-from-other-stores.pl nix-http-export.cgi
find-runtime-roots.pl build-remote.pl nix-reduce-build
nix-pull nix-push: readmanifest.pm readconfig.pm download-using-manifests.pl
install-exec-local: readmanifest.pm download-using-manifests.pl copy-from-other-stores.pl find-runtime-roots.pl
install-exec-local: readmanifest.pm download-using-manifests.pl find-runtime-roots.pl
$(INSTALL) -d $(DESTDIR)$(sysconfdir)/profile.d
$(INSTALL_PROGRAM) nix-profile.sh $(DESTDIR)$(sysconfdir)/profile.d/nix.sh
$(INSTALL) -d $(DESTDIR)$(libexecdir)/nix
$(INSTALL_DATA) readmanifest.pm $(DESTDIR)$(libexecdir)/nix
$(INSTALL_DATA) readconfig.pm $(DESTDIR)$(libexecdir)/nix
$(INSTALL_PROGRAM) download-using-manifests.pl $(DESTDIR)$(libexecdir)/nix
$(INSTALL_PROGRAM) find-runtime-roots.pl $(DESTDIR)$(libexecdir)/nix
$(INSTALL_PROGRAM) generate-patches.pl $(DESTDIR)$(libexecdir)/nix
$(INSTALL_PROGRAM) build-remote.pl $(DESTDIR)$(libexecdir)/nix
$(INSTALL) -d $(DESTDIR)$(libexecdir)/nix/substituters
$(INSTALL_PROGRAM) download-using-manifests.pl $(DESTDIR)$(libexecdir)/nix/substituters
$(INSTALL_PROGRAM) copy-from-other-stores.pl $(DESTDIR)$(libexecdir)/nix/substituters
$(INSTALL) -d $(DESTDIR)$(sysconfdir)/nix
include ../substitute.mk
@@ -33,10 +31,9 @@ EXTRA_DIST = nix-collect-garbage.in \
readconfig.pm.in \
nix-build.in \
download-using-manifests.pl.in \
copy-from-other-stores.pl.in \
generate-patches.pl.in \
nix-pack-closure.in nix-unpack-closure.in \
nix-copy-closure.in \
find-runtime-roots.pl.in \
build-remote.pl.in \
nix-reduce-build.in \
nix-http-export.cgi.in
nix-reduce-build.in

View File

@@ -3,7 +3,6 @@
use strict;
use Fcntl ':flock';
use English '-no_match_vars';
use IO::Handle;
# General operation:
#
@@ -24,12 +23,16 @@ use IO::Handle;
my $loadIncreased = 0;
my ($amWilling, $localSystem, $neededSystem, $drvPath, $maxSilentTime) = @ARGV;
$maxSilentTime = 0 unless defined $maxSilentTime;
my $amWilling = shift @ARGV;
my $localSystem = shift @ARGV;
my $neededSystem = shift @ARGV;
my $drvPath = shift @ARGV;
sub sendReply {
my $reply = shift;
print STDERR "# $reply\n";
open OUT, ">&3" or die;
print OUT "$reply\n";
close OUT;
}
sub decline {
@@ -44,25 +47,30 @@ mkdir $currentLoad, 0777 or die unless -d $currentLoad;
my $conf = $ENV{"NIX_REMOTE_SYSTEMS"};
decline if !defined $conf || ! -e $conf;
my $canBuildLocally = $amWilling && ($localSystem eq $neededSystem);
# Decline if the local system can do the build.
decline if $amWilling && ($localSystem eq $neededSystem);
# Otherwise find a willing remote machine.
my %machines;
my %systemTypes;
my %sshKeys;
my %maxJobs;
my %curJobs;
# Read the list of machines.
my @machines;
open CONF, "< $conf" or die;
while (<CONF>) {
chomp;
s/\#.*$//g;
next if /^\s*$/;
/^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\d+)(\s+([0-9\.]+))?\s*$/ or die;
push @machines,
{ hostName => $1
, systemTypes => [split(/,/, $2)]
, sshKeys => $3
, maxJobs => $4
, speedFactor => 1.0 * ($6 || 1)
};
/^\s*(\S+)\s+(\S+)\s+(\S+)\s+(\d+)\s*$/ or die;
$machines{$1} = "";
$systemTypes{$1} = $2;
$sshKeys{$1} = $3;
$maxJobs{$1} = $4;
}
close CONF;
@@ -74,56 +82,35 @@ open MAINLOCK, ">>$mainLock" or die;
flock(MAINLOCK, LOCK_EX) or die;
sub openSlotLock {
my ($machine, $slot) = @_;
my $slotLockFn = "$currentLoad/" . (join '+', @{$machine->{systemTypes}}) . "-" . $machine->{hostName} . "-$slot";
my $slotLock = new IO::Handle;
open $slotLock, ">>$slotLockFn" or die;
return $slotLock;
}
# Find all machine that can execute this build, i.e., that support
# builds for the given platform and are not at their job limit.
# Find a suitable system.
my $rightType = 0;
my @available = ();
LOOP: foreach my $cur (@machines) {
if (grep { $neededSystem eq $_ } @{$cur->{systemTypes}}) {
my $machine;
LOOP: foreach my $cur (keys %machines) {
if ($neededSystem eq $systemTypes{$cur}) {
$rightType = 1;
# We have a machine of the right type. Determine the load on
# the machine.
# We have a machine of the right type. Try to get a lock on
# one of the machine's lock files.
my $slot = 0;
my $load = 0;
my $free;
while ($slot < $cur->{maxJobs}) {
my $slotLock = openSlotLock($cur, $slot);
if (flock($slotLock, LOCK_EX | LOCK_NB)) {
$free = $slot unless defined $free;
flock($slotLock, LOCK_UN) or die;
} else {
$load++;
}
close $slotLock;
while ($slot < $maxJobs{$cur}) {
my $slotLock = "$currentLoad/$cur-$slot";
open SLOTLOCK, ">>$slotLock" or die;
if (flock(SLOTLOCK, LOCK_EX | LOCK_NB)) {
$machine = $cur;
last LOOP;
}
close SLOTLOCK;
$slot++;
}
push @available, { machine => $cur, load => $load, free => $free }
if $load < $cur->{maxJobs};
}
}
if (defined $ENV{NIX_DEBUG_HOOK}) {
print STDERR "load on " . $_->{machine}->{hostName} . " = " . $_->{load} . "\n"
foreach @available;
}
close MAINLOCK;
# Didn't find any available machine? Then decline or postpone.
if (scalar @available == 0) {
# Postpone if we have a machine of the right type, except if the
# local system can and wants to do the build.
if ($rightType && !$canBuildLocally) {
# Didn't find one?
if (!defined $machine) {
if ($rightType) {
sendReply "postpone";
exit 0;
} else {
@@ -131,52 +118,21 @@ if (scalar @available == 0) {
}
}
# Prioritise the available machines as follows:
# - First by load divided by speed factor, rounded to the nearest
# integer. This causes fast machines to be preferred over slow
# machines with similar loads.
# - Then by speed factor.
# - Finally by load.
sub lf { my $x = shift; return int($x->{load} / $x->{machine}->{speedFactor} + 0.4999); }
@available = sort
{ lf($a) <=> lf($b)
|| $b->{machine}->{speedFactor} <=> $a->{machine}->{speedFactor}
|| $a->{load} <=> $b->{load}
} @available;
# Select the best available machine and lock a free slot.
my $selected = $available[0];
my $machine = $selected->{machine};
my $slotLock = openSlotLock($machine, $selected->{free});
flock($slotLock, LOCK_EX | LOCK_NB) or die;
utime undef, undef, $slotLock;
close MAINLOCK;
# Tell Nix we've accepted the build.
# Yes we did, accept.
sendReply "accept";
if (defined $ENV{NIX_DEBUG_HOOK}) {
my $hostName = $machine->{hostName};
my $sp = $machine->{speedFactor};
print STDERR "building `$drvPath' on `$hostName' - $sp - " . $selected->{free} . "\n";
sleep 10;
exit 0;
}
my $x = <STDIN>;
open IN, "<&4" or die;
my $x = <IN>;
chomp $x;
#print "got $x\n";
close IN;
if ($x ne "okay") {
exit 0;
}
# Do the actual build.
my $hostName = $machine->{hostName};
print STDERR "building `$drvPath' on `$hostName'\n";
# Do the actual job.
print "BUILDING REMOTE: $drvPath on $machine\n";
# Make sure that we don't get any SSH passphrase or host key popups -
# if there is any problem it should fail, not do something
@@ -185,10 +141,10 @@ $ENV{"DISPLAY"} = "";
$ENV{"SSH_PASSWORD_FILE="} = "";
$ENV{"SSH_ASKPASS="} = "";
my $sshOpts = "-i " . $machine->{sshKeys} . " -x";
my $sshOpts = "-i $sshKeys{$machine} -x";
# Hack to support Cygwin: if we login without a password, we don't
# have exactly the same rights as when we do. This causes the
# have exactly the same right as when we do. This causes the
# Microsoft C compiler to fail with certain flags:
#
# http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=99676
@@ -198,8 +154,8 @@ my $sshOpts = "-i " . $machine->{sshKeys} . " -x";
# password. (It only calls this command when there is no controlling
# terminal, but Nix ensures that is is the case. When doing this
# manually, use setsid(1).)
if ($machine->{sshKeys} =~ /^password:/) {
my $passwordFile = $machine->{sshKeys};
if ($sshKeys{$machine} =~ /^password:/) {
my $passwordFile = $sshKeys{$machine};
$passwordFile =~ s/^password://;
$sshOpts = "ssh -x";
$ENV{"SSH_PASSWORD_FILE"} = $passwordFile;
@@ -217,40 +173,36 @@ $inputs =~ s/\n/ /g;
my $outputs = `cat outputs`; die if ($? != 0);
$outputs =~ s/\n/ /g;
print "copying inputs...\n";
print "COPYING INPUTS...\n";
my $maybeSign = "";
$maybeSign = "--sign" if -e "/nix/etc/nix/signing-key.sec";
system("NIX_SSHOPTS=\"$sshOpts\" @bindir@/nix-copy-closure $hostName $maybeSign $drvPath $inputs") == 0
or die "cannot copy inputs to $hostName: $?";
system("NIX_SSHOPTS=\"$sshOpts\" nix-copy-closure $machine $maybeSign $drvPath $inputs") == 0
or die "cannot copy inputs to $machine: $?";
print "building...\n";
print "BUILDING...\n";
my $buildFlags = "--max-silent-time $maxSilentTime";
system("ssh $sshOpts $machine 'nix-store -rvvK $drvPath'") == 0
or die "remote build on $machine failed: $?";
# `-tt' forces allocation of a pseudo-terminal. This is required to
# make the remote nix-store process receive a signal when the
# connection dies. Without it, the remote process might continue to
# run indefinitely (that is, until it next tries to write to
# stdout/stderr).
if (system("ssh -tt $sshOpts $hostName 'nix-store --realise $buildFlags $drvPath > /dev/null'") != 0) {
# If we couldn't run ssh or there was an ssh problem (indicated by
# exit code 255), then we return exit code 1; otherwise we assume
# that the builder failed, which we indicated to Nix using exit
# code 100. It's important to distinguish between the two because
# the first is a transient failure and the latter is permanent.
my $res = $? == -1 || ($? >> 8) == 255 ? 1 : 100;
print STDERR "build of `$drvPath' on `$hostName' failed with exit code $?\n";
exit $res;
}
print "build of `$drvPath' on `$hostName' succeeded\n";
print "REMOTE BUILD DONE: $drvPath on $machine\n";
foreach my $output (split '\n', $outputs) {
my $maybeSignRemote = "";
$maybeSignRemote = "--sign" if $UID != 0;
system("ssh $sshOpts $hostName 'nix-store --export $maybeSignRemote $output' | @bindir@/nix-store --import > /dev/null") == 0
or die "cannot copy $output from $hostName: $?";
system("ssh $sshOpts $machine 'nix-store --export $maybeSignRemote $output' > dump") == 0
or die "cannot copy $output from $machine: $?";
# This doesn't work yet, since the caller has a lock on the output
# path. We should move towards lock-free invocation of build
# hooks and substitutes.
#system("nix-store --import < dump") == 0
# or die "cannot import $output: $?";
# Hack: skip the first 8 bytes (the nix-store --export next
# archive marker). The archive follows.
system("(dd bs=1 count=8 of=/dev/null && cat) < dump | nix-store --restore $output") == 0
or die "cannot restore $output: $?";
}

View File

@@ -1,98 +0,0 @@
#! @perl@ -w
use strict;
use File::Basename;
use IO::Handle;
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
STDOUT->autoflush(1);
my @remoteStoresAll = split ':', ($ENV{"NIX_OTHER_STORES"} or "");
my @remoteStores;
foreach my $dir (@remoteStoresAll) {
push @remoteStores, glob($dir);
}
sub findStorePath {
my $storePath = shift;
my $storePathName = basename $storePath;
foreach my $store (@remoteStores) {
# Determine whether $storePath exists by looking for the
# existence of the info file, and if so, get store path info
# from that file. This rather breaks abstraction: we should
# be using `nix-store' for that. But right now there is no
# good way to tell nix-store to access a store mounted under a
# different location (there's $NIX_STORE, but that only works
# if the remote store is mounted under its "real" location).
my $infoFile = "$store/var/nix/db/info/$storePathName";
my $storePath2 = "$store/store/$storePathName";
if (-f $infoFile && -e $storePath2) {
return ($infoFile, $storePath2);
}
}
}
if ($ARGV[0] eq "--query") {
while (<STDIN>) {
my $cmd = $_; chomp $cmd;
if ($cmd eq "have") {
my $storePath = <STDIN>; chomp $storePath;
(my $infoFile) = findStorePath $storePath;
print STDOUT ($infoFile ? "1\n" : "0\n");
}
elsif ($cmd eq "info") {
my $storePath = <STDIN>; chomp $storePath;
(my $infoFile) = findStorePath $storePath;
if (!$infoFile) {
print "0\n";
next; # not an error
}
print "1\n";
my $deriver = "";
my @references = ();
open INFO, "<$infoFile" or die "cannot read info file $infoFile\n";
while (<INFO>) {
chomp;
/^([\w-]+): (.*)$/ or die "bad info file";
my $key = $1;
my $value = $2;
if ($key eq "Deriver") { $deriver = $value; }
elsif ($key eq "References") { @references = split ' ', $value; }
}
close INFO;
print "$deriver\n";
print scalar @references, "\n";
print "$_\n" foreach @references;
print "0\n"; # !!! showing size not supported (yet)
}
else { die "unknown command `$cmd'"; }
}
}
elsif ($ARGV[0] eq "--substitute") {
die unless scalar @ARGV == 2;
my $storePath = $ARGV[1];
(my $infoFile, my $sourcePath) = findStorePath $storePath;
die unless $infoFile;
print "\n*** Copying `$storePath' from `$sourcePath'\n\n";
system("$binDir/nix-store --dump $sourcePath | $binDir/nix-store --restore $storePath") == 0
or die "cannot copy `$sourcePath' to `$storePath'";
}
else { die; }

View File

@@ -5,81 +5,10 @@ use readmanifest;
use POSIX qw(strftime);
use File::Temp qw(tempdir);
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
STDOUT->autoflush(1);
my $manifestDir = ($ENV{"NIX_MANIFESTS_DIR"} or "@localstatedir@/nix/manifests");
my $manifestDir = "@localstatedir@/nix/manifests";
my $logFile = "@localstatedir@/log/nix/downloads";
# Load all manifests.
my %narFiles;
my %localPaths;
my %patches;
for my $manifest (glob "$manifestDir/*.nixmanifest") {
my $version = readManifest($manifest, \%narFiles, \%localPaths, \%patches);
if ($version < 3) {
print STDERR "you have an old-style manifest `$manifest'; please delete it\n";
exit 1;
}
if ($version >= 10) {
print STDERR "manifest `$manifest' is too new; please delete it or upgrade Nix\n";
exit 1;
}
}
# Parse the arguments.
if ($ARGV[0] eq "--query") {
while (<STDIN>) {
my $cmd = $_; chomp $cmd;
if ($cmd eq "have") {
my $storePath = <STDIN>; chomp $storePath;
print STDOUT ((defined $narFiles{$storePath} or defined $localPaths{$storePath})
? "1\n" : "0\n");
}
elsif ($cmd eq "info") {
my $storePath = <STDIN>; chomp $storePath;
my $info;
if (defined $narFiles{$storePath}) {
$info = @{$narFiles{$storePath}}[0];
}
elsif (defined $localPaths{$storePath}) {
$info = @{$localPaths{$storePath}}[0];
}
else {
print "0\n";
next; # not an error
}
print "1\n";
print "$info->{deriver}\n";
my @references = split " ", $info->{references};
print scalar @references, "\n";
print "$_\n" foreach @references;
my $size = $info->{size} || 0;
print "$size\n";
}
else { die "unknown command `$cmd'"; }
}
exit 0;
}
elsif ($ARGV[0] ne "--substitute") {
die "syntax: $0 [--query-paths | --query-info PATHS... | --substitute PATH]\n";
}
die unless scalar @ARGV == 2;
my $targetPath = $ARGV[1];
open LOGFILE, ">>$logFile" or die "cannot open log file $logFile";
# Create a temporary directory.
my $tmpDir = tempdir("nix-download.XXXXXX", CLEANUP => 1, TMPDIR => 1)
@@ -91,7 +20,78 @@ my $tmpNar = "$tmpDir/nar";
my $tmpNar2 = "$tmpDir/nar2";
open LOGFILE, ">>$logFile" or die "cannot open log file $logFile";
# Load all manifests.
my %narFiles;
my %localPaths;
my %patches;
for my $manifest (glob "$manifestDir/*.nixmanifest") {
# print STDERR "reading $manifest\n";
if (readManifest($manifest, \%narFiles, \%localPaths, \%patches) < 3) {
print STDERR "you have an old-style manifest `$manifest'; please delete it\n";
exit 1;
}
}
# Parse the arguments.
if ($ARGV[0] eq "--query-paths") {
foreach my $storePath (keys %narFiles) { print "$storePath\n"; }
foreach my $storePath (keys %localPaths) { print "$storePath\n"; }
exit 0;
}
elsif ($ARGV[0] eq "--query-info") {
shift @ARGV;
foreach my $storePath (@ARGV) {
my $info;
if (defined $narFiles{$storePath}) {
$info = @{$narFiles{$storePath}}[0];
}
elsif (defined $localPaths{$storePath}) {
$info = @{$localPaths{$storePath}}[0];
}
else {
next; # not an error
}
print "$storePath\n";
print "$info->{deriver}\n";
my @references = split " ", $info->{references};
my $count = scalar @references;
print "$count\n";
foreach my $reference (@references) {
print "$reference\n";
}
my $isStateStorePath = `@bindir@/nix-state --is-state-store-path-download-using-manifests $storePath`;
if($isStateStorePath ne "true" && $isStateStorePath ne "false"){
die "The call for isStateStorePath must return true or false.....";
}
if($isStateStorePath eq "true"){
my @stateReferences = split " ", $info->{stateReferences};
my $scount = scalar @stateReferences;
print "$scount\n";
foreach my $stateReference (@stateReferences) {
print "$stateReference\n";
}
print "$info->{revision}\n";
}
}
exit 0;
}
elsif ($ARGV[0] ne "--substitute") {
die "syntax: $0 [--query-paths | --query-info PATHS... | --substitute PATH]\n";
}
die unless scalar @ARGV == 2;
my $targetPath = $ARGV[1];
my $date = strftime ("%F %H:%M:%S UTC", gmtime (time));
print LOGFILE "$$ get $targetPath $date\n";
@@ -105,7 +105,7 @@ foreach my $localPath (@{$localPathList}) {
my $sourcePath = $localPath->{copyFrom};
if (-e $sourcePath) {
print "\n*** Step 1/1: copying from $sourcePath\n";
system("$binDir/nix-store --dump $sourcePath | $binDir/nix-store --restore $targetPath") == 0
system("@bindir@/nix-store --dump $sourcePath | @bindir@/nix-store --restore $targetPath") == 0
or die "cannot copy `$sourcePath' to `$targetPath'";
exit 0;
}
@@ -154,7 +154,7 @@ addToQueue $targetPath;
sub isValidPath {
my $p = shift;
return system("$binDir/nix-store --check-validity '$p' 2> /dev/null") == 0;
return system("@bindir@/nix-store --check-validity '$p' 2> /dev/null") == 0;
}
sub parseHash {
@@ -188,13 +188,15 @@ while ($queueFront < scalar @queue) {
my ($baseHashAlgo, $baseHash) = parseHash $patch->{baseHash};
my $format = "--base32";
$format = "" if $baseHashAlgo eq "md5";
my $hash = `$binDir/nix-hash --type '$baseHashAlgo' $format "$patch->{basePath}"`;
my $hash = `@bindir@/nix-hash --type '$baseHashAlgo' $format "$patch->{basePath}"`;
chomp $hash;
# print " MY HASH is $hash\n";
if ($hash ne $baseHash) {
print LOGFILE "$$ rejecting $patch->{basePath}\n";
next;
}
}
# print " PATCH from $patch->{basePath}\n";
addToQueue $patch->{basePath};
addEdge $patch->{basePath}, $u, $patch->{size}, "patch", $patch;
}
@@ -202,12 +204,10 @@ while ($queueFront < scalar @queue) {
# Add NAR file edges to the start node.
my $narFileList = $narFiles{$u};
foreach my $narFile (@{$narFileList}) {
# !!! how to handle files whose size is not known in advance?
# For now, assume some arbitrary size (1 MB).
addEdge "start", $u, ($narFile->{size} || 1000000), "narfile", $narFile;
# print " NAR from $narFile->{url}\n";
addEdge "start", $u, $narFile->{size}, "narfile", $narFile;
if ($u eq $targetPath) {
my $size = $narFile->{size} || -1;
print LOGFILE "$$ full-download-would-be $size\n";
print LOGFILE "$$ full-download-would-be $narFile->{size}\n";
}
}
@@ -233,6 +233,8 @@ while (scalar @todo > 0) {
my $u_ = $graph{$u};
# print "IN $u $u_->{d}\n";
foreach my $edge (@{$u_->{edges}}) {
my $v_ = $graph{$edge->{end}};
if ($v_->{d} > $u_->{d} + $edge->{weight}) {
@@ -240,6 +242,7 @@ while (scalar @todo > 0) {
# Store the edge; to edge->start is actually the
# predecessor.
$v_->{pred} = $edge;
# print " RELAX $edge->{end} $v_->{d}\n";
}
}
}
@@ -261,18 +264,20 @@ while ($cur ne "start") {
my $curStep = 1;
my $maxStep = scalar @path;
sub downloadFile {
my $url = shift;
sub downloadFile {
my $url = shift;
my ($hashAlgo, $hash) = parseHash(shift);
$ENV{"PRINT_PATH"} = 1;
$ENV{"QUIET"} = 1;
my ($hash, $path) = `$binDir/nix-prefetch-url '$url'`;
$ENV{"NIX_HASH_ALGO"} = $hashAlgo;
my ($hash2, $path) = `@bindir@/nix-prefetch-url '$url' '$hash'`;
die "download of `$url' failed" unless $? == 0;
chomp $hash2;
chomp $path;
die "hash mismatch, expected $hash, got $hash2" if $hash ne $hash2;
return $path;
}
my $finalNarHash;
while (scalar @path > 0) {
my $edge = pop @path;
my $u = $edge->{start};
@@ -289,7 +294,7 @@ while (scalar @path > 0) {
# as a base to one or more patches. So turn the base path
# into a NAR archive, to which we can apply the patch.
print " packing base path...\n";
system("$binDir/nix-store --dump $v > $tmpNar") == 0
system("@bindir@/nix-store --dump $v > $tmpNar") == 0
or die "cannot dump `$v'";
}
}
@@ -302,7 +307,7 @@ while (scalar @path > 0) {
# Download the patch.
print " downloading patch...\n";
my $patchPath = downloadFile "$patch->{url}";
my $patchPath = downloadFile "$patch->{url}", "$patch->{hash}";
# Apply the patch to the NAR archive produced in step 1 (for
# the already present path) or a later step (for patch sequences).
@@ -317,23 +322,20 @@ while (scalar @path > 0) {
# This was the last patch. Unpack the final NAR archive
# into the target path.
print " unpacking patched archive...\n";
system("$binDir/nix-store --restore $v < $tmpNar2") == 0
system("@bindir@/nix-store --restore $v < $tmpNar2") == 0
or die "cannot unpack $tmpNar2 into `$v'";
}
$finalNarHash = $patch->{narHash};
}
elsif ($edge->{type} eq "narfile") {
my $narFile = $edge->{info};
print "downloading `$narFile->{url}' into `$v'\n";
my $size = $narFile->{size} || -1;
print LOGFILE "$$ narfile $narFile->{url} $size $v\n";
print LOGFILE "$$ narfile $narFile->{url} $narFile->{size} $v\n";
# Download the archive.
print " downloading archive...\n";
my $narFilePath = downloadFile "$narFile->{url}";
my $narFilePath = downloadFile "$narFile->{url}", "$narFile->{hash}";
if ($curStep < $maxStep) {
# The archive will be used a base to a patch.
@@ -342,39 +344,14 @@ while (scalar @path > 0) {
} else {
# Unpack the archive into the target path.
print " unpacking archive...\n";
system("@bunzip2@ < '$narFilePath' | $binDir/nix-store --restore '$v'") == 0
system("@bunzip2@ < '$narFilePath' | @bindir@/nix-store --restore '$v'") == 0
or die "cannot unpack `$narFilePath' into `$v'";
}
$finalNarHash = $narFile->{narHash};
}
$curStep++;
}
# Make sure that the hash declared in the manifest matches what we
# downloaded and unpacked.
if (defined $finalNarHash) {
my ($hashAlgo, $hash) = parseHash $finalNarHash;
# The hash in the manifest can be either in base-16 or base-32.
# Handle both.
my $extraFlag =
($hashAlgo eq "sha256" && length($hash) != 64)
? "--base32" : "";
my $hash2 = `@bindir@/nix-hash --type $hashAlgo $extraFlag $targetPath`
or die "cannot compute hash of path `$targetPath'";
chomp $hash2;
die "hash mismatch in downloaded path $targetPath; expected $hash, got $hash2"
if $hash ne $hash2;
} else {
die "cannot check integrity of the downloaded path since its hash is not known";
}
print LOGFILE "$$ success\n";
close LOGFILE;

View File

@@ -2,8 +2,6 @@
use strict;
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
my $addDrvLink = 0;
my $addOutLink = 1;
@@ -11,9 +9,6 @@ my $addOutLink = 1;
my $outLink;
my $drvLink;
my $dryRun = 0;
my $verbose = 0;
my @instArgs = ();
my @buildArgs = ();
my @exprs = ();
@@ -78,7 +73,7 @@ EOF
elsif ($arg eq "--attr" or $arg eq "-A") {
$n++;
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
die "$0: `--attr' requires an argument\n" unless $n < scalar @ARGV;
push @instArgs, ("--attr", $ARGV[$n]);
}
@@ -88,41 +83,12 @@ EOF
$n += 2;
}
elsif ($arg eq "--log-type") {
$n++;
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
push @instArgs, ($arg, $ARGV[$n]);
push @buildArgs, ($arg, $ARGV[$n]);
}
elsif ($arg eq "--option") {
die "$0: `$arg' requires two arguments\n" unless $n + 2 < scalar @ARGV;
push @instArgs, ($arg, $ARGV[$n + 1], $ARGV[$n + 2]);
push @buildArgs, ($arg, $ARGV[$n + 1], $ARGV[$n + 2]);
$n += 2;
}
elsif ($arg eq "--max-jobs" or $arg eq "-j" or $arg eq "--max-silent-time" or $arg eq "--log-type") {
elsif ($arg eq "--max-jobs" or $arg eq "-j" or $arg eq "--max-silent-time") {
$n++;
die "$0: `$arg' requires an argument\n" unless $n < scalar @ARGV;
push @buildArgs, ($arg, $ARGV[$n]);
}
elsif ($arg eq "--dry-run") {
push @buildArgs, "--dry-run";
$dryRun = 1;
}
elsif ($arg eq "--show-trace") {
push @instArgs, $arg;
}
elsif ($arg eq "--verbose" or substr($arg, 0, 2) eq "-v") {
push @buildArgs, $arg;
push @instArgs, $arg;
$verbose = 1;
}
elsif (substr($arg, 0, 1) eq "-") {
push @buildArgs, $arg;
}
@@ -151,29 +117,21 @@ foreach my $expr (@exprs) {
# Instantiate.
my @drvPaths;
# !!! would prefer the perl 5.8.0 pipe open feature here.
my $pid = open(DRVPATHS, "-|") || exec "$binDir/nix-instantiate", "--add-root", $drvLink, "--indirect", @instArgs, $expr;
my $pid = open(DRVPATHS, "-|") || exec "@bindir@/nix-instantiate", "--add-root", $drvLink, "--indirect", @instArgs, $expr;
while (<DRVPATHS>) {chomp; push @drvPaths, $_;}
if (!close DRVPATHS) {
die "nix-instantiate killed by signal " . ($? & 127) . "\n" if ($? & 127);
exit 1;
}
close DRVPATHS or exit 1;
foreach my $drvPath (@drvPaths) {
my $target = readlink $drvPath or die "cannot read symlink `$drvPath'";
print STDERR "derivation is $target\n" if $verbose;
print STDERR "store derivation is $target\n";
}
# Build.
my @outPaths;
$pid = open(OUTPATHS, "-|") || exec "$binDir/nix-store", "--add-root", $outLink, "--indirect", "-rv",
$pid = open(OUTPATHS, "-|") || exec "@bindir@/nix-store", "--add-root", $outLink, "--indirect", "-rv",
@buildArgs, @drvPaths;
while (<OUTPATHS>) {chomp; push @outPaths, $_;}
if (!close OUTPATHS) {
die "nix-store killed by signal " . ($? & 127) . "\n" if ($? & 127);
exit 1;
}
next if $dryRun;
close OUTPATHS or exit 1;
foreach my $outPath (@outPaths) {
my $target = readlink $outPath or die "cannot read symlink `$outPath'";

View File

@@ -78,9 +78,6 @@ sub removeChannel {
sub update {
readChannels;
# Create the manifests directory if it doesn't exist.
mkdir "$stateDir/manifests", 0755 unless -e "$stateDir/manifests";
# Do we have write permission to the manifests directory? If not,
# then just skip pulling the manifest and just download the Nix
# expressions. If the user is a non-privileged user in a
@@ -88,6 +85,11 @@ sub update {
# source.
if (-W "$stateDir/manifests") {
# Remove all the old manifests.
for my $manifest (glob "$stateDir/manifests/*.nixmanifest") {
unlink $manifest or die "cannot remove `$manifest': $!";
}
# Pull cache manifests.
foreach my $url (@channels) {
#print "pulling cache manifest from `$url'\n";
@@ -123,13 +125,15 @@ sub update {
my $rootFile = "$rootsDir/per-user/$userName/channels";
# Build the Nix expression.
# Instantiate the Nix expression.
print "unpacking channel Nix expressions...\n";
my $outPath = `\\
@bindir@/nix-build --out-link '$rootFile' --drv-link '$rootFile'.tmp \\
@datadir@/nix/corepkgs/channels/unpack.nix \\
--argstr system @system@ --arg inputs '$inputs'`
or die "cannot unpack the channels";
my $storeExpr = `@bindir@/nix-instantiate --add-root '$rootFile'.tmp @datadir@/nix/corepkgs/channels/unpack.nix --argstr system @system@ --arg inputs '$inputs'`
or die "cannot instantiate Nix expression";
chomp $storeExpr;
# Build the resulting derivation.
my $outPath = `@bindir@/nix-store --add-root '$rootFile' -r '$storeExpr'`
or die "cannot realise store expression";
chomp $outPath;
unlink "$rootFile.tmp";

View File

@@ -4,8 +4,6 @@ use strict;
my $profilesDir = "@localstatedir@/nix/profiles";
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
# Process the command line arguments.
my @args = ();
@@ -36,7 +34,7 @@ sub removeOldGenerations {
$name = $dir . "/" . $name;
if (-l $name && (readlink($name) =~ /link/)) {
print STDERR "removing old generations of profile $name\n";
system("$binDir/nix-env", "-p", $name, "--delete-generations", "old");
system("@bindir@/nix-env", "-p", $name, "--delete-generations", "old");
}
elsif (! -l $name && -d $name) {
removeOldGenerations $name;
@@ -50,4 +48,4 @@ removeOldGenerations $profilesDir if $removeOld;
# Run the actual garbage collector.
exec "$binDir/nix-store", "--gc", @args;
exec "@bindir@/nix-store", "--gc", @args;

View File

@@ -1,6 +1,7 @@
#! @perl@ -w
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
my $binDir = $ENV{"NIX_BIN_DIR"};
$binDir = "@bindir@" unless defined $binDir;
if (scalar @ARGV < 1) {
@@ -55,17 +56,29 @@ while (@ARGV) {
if ($toMode) { # Copy TO the remote machine.
my @allStorePaths;
my %storePathsSeen;
# Get the closure of this path.
my $pid = open(READ, "$binDir/nix-store --query --requisites @storePaths|") or die;
foreach my $storePath (@storePaths) {
# $arg might be a symlink to the store, so resolve it.
my $storePath2 = (`$binDir/nix-store --query --resolve '$storePath'`
or die "cannot resolve `$storePath'");
chomp $storePath2;
# Get the closure of this path.
my $pid = open(READ,
"$binDir/nix-store --query --requisites '$storePath2'|") or die;
while (<READ>) {
chomp;
die "bad: $_" unless /^\//;
push @allStorePaths, $_;
}
while (<READ>) {
chomp;
die "bad: $_" unless /^\//;
if (!defined $storePathsSeen{$_}) {
push @allStorePaths, $_;
$storePathsSeen{$_} = 1;
}
}
close READ or die "nix-store failed: $?";
close READ or die "nix-store failed: $?";
}
# Ask the remote host which paths are invalid.
@@ -99,11 +112,15 @@ else { # Copy FROM the remote machine.
"ssh @sshOpts $sshHost nix-store --query --requisites @storePaths|") or die;
my @allStorePaths;
my %storePathsSeen;
while (<READ>) {
chomp;
die "bad: $_" unless /^\//;
push @allStorePaths, $_;
if (!defined $storePathsSeen{$_}) {
push @allStorePaths, $_;
$storePathsSeen{$_} = 1;
}
}
close READ or die "nix-store on remote machine `$sshHost' failed: $?";

View File

@@ -1,51 +0,0 @@
#! /bin/sh
export HOME=/tmp
export NIX_REMOTE=daemon
TMP_DIR="${TMP_DIR:-/tmp/nix-export}"
@coreutils@/mkdir -p "$TMP_DIR" || true
@coreutils@/chmod a+r "$TMP_DIR"
needed_path="?$QUERY_STRING"
needed_path="${needed_path#*[?&]needed_path=}"
needed_path="${needed_path%%&*}"
#needed_path="$(echo $needed_path | ./unhttp)"
needed_path="${needed_path//%2B/+}"
needed_path="${needed_path//%3D/=}"
echo needed_path: "$needed_path" >&2
NIX_STORE="${NIX_STORE_DIR:-/nix/store}"
echo NIX_STORE: "${NIX_STORE}" >&2
full_path="${NIX_STORE}"/"$needed_path"
if [ "$needed_path" != "${needed_path%.drv}" ]; then
echo "Status: 403 You should create the derivation file yourself"
echo "Content-Type: text/plain"
echo
echo "Refusing to disclose derivation contents"
exit
fi
if @bindir@/nix-store --check-validity "$full_path"; then
if ! [ -e nix-export/"$needed_path".nar.gz ]; then
@bindir@/nix-store --export "$full_path" | @gzip@ > "$TMP_DIR"/"$needed_path".nar.gz
@coreutils@/ln -fs "$TMP_DIR"/"$needed_path".nar.gz nix-export/"$needed_path".nar.gz
fi;
echo "Status: 301 Moved"
echo "Location: nix-export/"$needed_path".nar.gz"
echo
else
echo "Status: 404 No such path found"
echo "Content-Type: text/plain"
echo
echo "Path not found:"
echo "$needed_path"
echo "checked:"
echo "$full_path"
fi

View File

@@ -3,8 +3,6 @@
use strict;
use File::Temp qw(tempdir);
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
sub usageError {
print STDERR <<EOF;
@@ -61,7 +59,7 @@ if ($interactive && !defined $ENV{"NIX_HAVE_TERMINAL"}) {
$ENV{"NIX_HAVE_TERMINAL"} = "1";
$ENV{"LD_LIBRARY_PATH"} = "";
foreach my $term ("xterm", "konsole", "gnome-terminal", "xterm") {
exec($term, "-e", "$binDir/nix-install-package", @ARGV);
exec($term, "-e", "@bindir@/nix-install-package", @ARGV);
}
die "cannot execute `xterm'";
}
@@ -123,18 +121,13 @@ if ($interactive) {
}
# Store the manifest in the temporary directory so that we don't
# pollute /nix/var/nix/manifests.
$ENV{NIX_MANIFESTS_DIR} = $tmpDir;
print "\nPulling manifests...\n";
system("$binDir/nix-pull", $manifestURL) == 0
system("@bindir@/nix-pull", $manifestURL) == 0
or barf "nix-pull failed: $?";
print "\nInstalling package...\n";
system("$binDir/nix-env", "--install", $outPath, "--force-name", $drvName, @extraNixEnvArgs) == 0
system("@bindir@/nix-env", "--install", $outPath, "--force-name", $drvName, @extraNixEnvArgs) == 0
or barf "nix-env failed: $?";

View File

@@ -0,0 +1,75 @@
#! @perl@ -w
# This tool computes the closure of a path (using "nix-store --query
# --requisites") and puts the contents of each path in the closure in
# a big NAR archive that can be installed on another Nix installation
# using "nix-unpack-closure".
# TODO: make this program "streamy", i.e., don't use a temporary
# directory.
use strict;
use File::Temp qw(tempdir);
my $binDir = $ENV{"NIX_BIN_DIR"};
$binDir = "@bindir@" unless defined $binDir;
my $tmpDir = tempdir("nix-pack-closure.XXXXXX", CLEANUP => 1, TMPDIR => 1)
or die "cannot create a temporary directory";
mkdir "$tmpDir/contents", 0755 or die;
mkdir "$tmpDir/references", 0755 or die;
mkdir "$tmpDir/derivers", 0755 or die;
open TOPLEVEL, ">$tmpDir/top-level" or die;
my %storePaths;
while (@ARGV) {
my $storePath = shift @ARGV;
# $storePath might be a symlink to the store, so resolve it.
$storePath = (`$binDir/nix-store --query --resolve '$storePath'`
or die "cannot resolve `$storePath'");
chomp $storePath;
print TOPLEVEL $storePath, "\n";
# Get the closure of this path.
my $pid = open(READ,
"$binDir/nix-store --query --requisites '$storePath'|") or die;
while (<READ>) {
chomp;
die "bad: $_" unless /^\//;
$storePaths{$_} = "";
}
close READ or die "nix-store failed: $?";
}
close TOPLEVEL or die;
foreach my $storePath (sort(keys %storePaths)) {
print STDERR "packing `$storePath'...\n";
$storePath =~ /\/([^\/]+)$/;
my $name = $1;
system("$binDir/nix-store --dump '$storePath' > $tmpDir/contents/$name") == 0
or die "nix-store --dump failed on `$storePath': $?";
system("$binDir/nix-store --query --references '$storePath' > $tmpDir/references/$name") == 0
or die "nix-store --query --references failed on `$storePath': $?";
system("$binDir/nix-store --query --deriver '$storePath' > $tmpDir/derivers/$name") == 0
or die "nix-store --query --deriver failed on `$storePath': $?";
}
# Write a NAR archive of everything to standard output.
system("nix-store --dump '$tmpDir'") == 0
or die "nix-store --dump failed";

View File

@@ -37,7 +37,6 @@ fi
mkTempDir() {
if test -n "$tmpPath"; then return; fi
local i=0
while true; do
if test -z "$TMPDIR"; then TMPDIR=/tmp; fi
@@ -60,32 +59,11 @@ removeTempDir() {
doDownload() {
@curl@ $cacheFlags --fail --location --max-redirs 20 --disable-epsv \
@curl@ $cacheFlags --fail -# --location --max-redirs 20 --disable-epsv \
--cookie-jar $tmpPath/cookies "$url" -o $tmpFile
}
# Hack to support the mirror:// scheme from Nixpkgs.
if test "${url:0:9}" = "mirror://"; then
if test -z "$NIXPKGS_ALL"; then
echo "Resolving mirror:// URLs requires Nixpkgs. Please point \$NIXPKGS_ALL at a Nixpkgs tree." >&2
exit 1
fi
mkTempDir
nix-build "$NIXPKGS_ALL" -A resolveMirrorURLs --argstr url "$url" -o $tmpPath/urls > /dev/null
expanded=($(cat $tmpPath/urls))
if test "${#expanded[*]}" = 0; then
echo "$0: cannot resolve $url." >&2
exit 1
fi
echo "$url expands to ${expanded[*]} (using ${expanded[0]})" >&2
url="${expanded[0]}"
fi
# If we don't know the hash or a file with that hash doesn't exist,
# download the file and add it to the store.
if test -z "$finalPath"; then
@@ -100,7 +78,7 @@ if test -z "$finalPath"; then
# garbage-collected independently.
if test -n "$NIX_DOWNLOAD_CACHE"; then
echo -n "$url" > $tmpPath/url
urlHash=$(@bindir@/nix-hash --type sha256 --base32 --flat $tmpPath/url)
urlHash=$(nix-hash --type sha256 --base32 --flat $tmpPath/url)
echo "$url" > "$NIX_DOWNLOAD_CACHE/$urlHash.url"
cachedHashFN="$NIX_DOWNLOAD_CACHE/$urlHash.$hashType"
cachedTimestampFN="$NIX_DOWNLOAD_CACHE/$urlHash.stamp"

View File

@@ -7,12 +7,5 @@ if test -n "$HOME"; then
@coreutils@/ln -s "$_NIX_DEF_LINK" "$NIX_LINK"
fi
export PATH=$NIX_LINK/bin:$PATH
fi
# This is a quick hack to make fontconfig-based packages in Nixpkgs
# work out of the box on non-NixOS systems. Of course, we should
# really fix fontconfig...
if test -z "$FONTCONFIG_FILE" -a -e /etc/fonts/fonts.conf; then
export FONTCONFIG_FILE=/etc/fonts/fonts.conf
export PATH=$NIX_LINK/bin:@prefix@/bin:$PATH
fi

View File

@@ -7,23 +7,28 @@ use readmanifest;
my $tmpDir = tempdir("nix-pull.XXXXXX", CLEANUP => 1, TMPDIR => 1)
or die "cannot create a temporary directory";
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
my $libexecDir = ($ENV{"NIX_LIBEXEC_DIR"} or "@libexecdir@");
my $storeDir = ($ENV{"NIX_STORE_DIR"} or "@storedir@");
my $stateDir = ($ENV{"NIX_STATE_DIR"} or "@localstatedir@/nix");
my $manifestDir = ($ENV{"NIX_MANIFESTS_DIR"} or "$stateDir/manifests");
my $binDir = $ENV{"NIX_BIN_DIR"};
$binDir = "@bindir@" unless defined $binDir;
my $libexecDir = $ENV{"NIX_LIBEXEC_DIR"};
$libexecDir = "@libexecdir@" unless defined $libexecDir;
my $stateDir = $ENV{"NIX_STATE_DIR"};
$stateDir = "@localstatedir@/nix" unless defined $stateDir;
my $storeDir = $ENV{"NIX_STORE_DIR"};
$storeDir = "@storedir@" unless defined $storeDir;
my $storeStateDir = $ENV{"NIX_STORE_STATE_DIR"};
$storeStateDir = "@storestatedir@" unless defined $storeStateDir;
my $ext3cowheader = $ENV{"NIX_EXT3_COW_HEADER"};
$ext3cowheader = "@ext3cowheader@" unless defined $ext3cowheader;
# Prevent access problems in shared-stored installations.
umask 0022;
# Create the manifests directory if it doesn't exist.
if (! -e $manifestDir) {
mkdir $manifestDir, 0755 or die "cannot create directory `$manifestDir'";
}
# Process the URLs specified on the command line.
my %narFiles;
my %localPaths;
@@ -51,7 +56,7 @@ sub processURL {
# First see if a bzipped manifest is available.
if (system("@curl@ --fail --silent --head '$url'.bz2 > /dev/null") == 0) {
print "fetching list of Nix archives at `$url.bz2'...\n";
print "obtaining list of Nix archives at `$url.bz2'...\n";
my $bzipped = downloadFile "$url.bz2";
$manifest = "$tmpDir/MANIFEST";
@@ -69,11 +74,10 @@ sub processURL {
print "obtaining list of Nix archives at `$url'...\n";
$manifest = downloadFile $url;
}
my $version = readManifest($manifest, \%narFiles, \%localPaths, \%patches);
die "`$url' is not a manifest or it is too old (i.e., for Nix <= 0.7)\n" if $version < 3;
die "manifest `$url' is too new\n" if $version >= 5;
if (readManifest($manifest, \%narFiles, \%localPaths, \%patches) < 3) {
die "`$url' is not manifest or it is too old (i.e., for Nix <= 0.7)\n";
}
if ($skipWrongStore) {
foreach my $path (keys %narFiles) {
@@ -92,31 +96,11 @@ sub processURL {
my $hash = `$binDir/nix-hash --flat '$manifest'`
or die "cannot hash `$manifest'";
chomp $hash;
my $urlFile = "$manifestDir/$baseName-$hash.url";
open URL, ">$urlFile" or die "cannot create `$urlFile'";
print URL "$url";
close URL;
my $finalPath = "$manifestDir/$baseName-$hash.nixmanifest";
unlink $finalPath if -e $finalPath;
symlink("$manifest", "$finalPath")
my $finalPath = "$stateDir/manifests/$baseName-$hash.nixmanifest";
system("@coreutils@/ln", "-sfn", "$manifest", "$finalPath") == 0
or die "cannot link `$finalPath to `$manifest'";
# Delete all old manifests downloaded from this URL.
for my $urlFile2 (glob "$manifestDir/*.url") {
next if $urlFile eq $urlFile2;
open URL, "<$urlFile2" or die;
my $url2 = <URL>;
chomp $url2;
close URL;
next unless $url eq $url2;
my $base = $urlFile2; $base =~ s/.url$//;
unlink "${base}.url";
unlink "${base}.nixmanifest";
}
}
while (@ARGV) {

View File

@@ -16,7 +16,8 @@ my $curl = "@curl@ --fail --silent";
my $extraCurlFlags = ${ENV{'CURL_FLAGS'}};
$curl = "$curl $extraCurlFlags" if defined $extraCurlFlags;
my $binDir = $ENV{"NIX_BIN_DIR"} || "@bindir@";
my $binDir = $ENV{"NIX_BIN_DIR"};
$binDir = "@bindir@" unless defined $binDir;
my $dataDir = $ENV{"NIX_DATA_DIR"};
$dataDir = "@datadir@" unless defined $dataDir;
@@ -106,7 +107,7 @@ foreach my $storePath (@storePaths) {
# Construct a Nix expression that creates a Nix archive.
my $nixexpr =
"((import $dataDir/nix/corepkgs/nar/nar.nix) " .
"{storePath = builtins.storePath \"$storePath\"; system = \"@system@\"; hashAlgo = \"$hashAlgo\";}) ";
"{storePath = builtins.toPath \"$storePath\"; system = \"@system@\"; hashAlgo = \"$hashAlgo\";}) ";
print NIX $nixexpr;
}
@@ -128,7 +129,7 @@ while (<READ>) {
close READ or die "nix-instantiate failed: $?";
# Build the derivations.
# Realise the store expressions.
print STDERR "creating archives...\n";
my @narPaths;
@@ -140,7 +141,12 @@ while (scalar @tmp > 0) {
my @tmp2 = @tmp[0..$n - 1];
@tmp = @tmp[$n..scalar @tmp - 1];
my $pid = open(READ, "$binDir/nix-store --realise @tmp2|")
# Note: we disable build hooks because of the impure path
# reference (see above). Even if that is fixed, using a hook
# probably wouldn't make that much sense; pumping lots of data
# around just to compress them won't gain that much.
$ENV{"NIX_BUILD_HOOK"} = "";
my $pid = open(READ, "$binDir/nix-store --no-build-hook --realise @tmp2|")
or die "cannot run nix-store";
while (<READ>) {
chomp;
@@ -218,14 +224,13 @@ writeManifest $manifest, \%narFiles, \%patches;
sub copyFile {
my $src = shift;
my $dst = shift;
my $tmp = "$dst.tmp.$$";
system("@coreutils@/cp", $src, $tmp) == 0 or die "cannot copy file";
rename($tmp, $dst) or die "cannot rename file: $!";
system("@coreutils@/cp", $src, "$dst.tmp") == 0 or die "cannot copy file";
rename("$dst.tmp", "$dst") or die "cannot rename file";
}
# Upload/copy the archives.
print STDERR "uploading/copying archives...\n";
# Upload the archives.
print STDERR "uploading archives...\n";
sub archiveExists {
my $name = shift;
@@ -239,12 +244,9 @@ foreach my $narArchive (@narArchives) {
my $basename = $1;
if ($localCopy) {
# Since nix-push creates $dst atomically, if it exists we
# don't have to copy again.
my $dst = "$localArchivesDir/$basename";
if (! -f "$localArchivesDir/$basename") {
print STDERR " $narArchive\n";
copyFile $narArchive, $dst;
copyFile $narArchive, "$localArchivesDir/$basename";
}
}
else {

View File

@@ -3,30 +3,10 @@
WORKING_DIRECTORY=$(mktemp -d "${TMPDIR:-/tmp}"/nix-reduce-build-XXXXXX);
cd "$WORKING_DIRECTORY";
if test -z "$1" || test "a--help" = "a$1" ; then
echo 'nix-reduce-build (paths or Nix expressions) -- (package sources)' >&2
if test -z "$1" ; then
echo 'nix-reduce-build (paths or Nix expressions) -- (logins at remote computers)' >&2
echo As in: >&2
echo nix-reduce-build /etc/nixos/nixos -- ssh://user@somewhere.nowhere.example.org >&2
echo nix-reduce-build /etc/nixos/nixos -- \\
echo " " \''http://somewhere.nowhere.example.org/nix/nix-http-export.cgi?needed_path='\' >&2
echo " store path name will be added into the end of the URL" >&2
echo nix-reduce-build /etc/nixos/nixos -- file://home/user/nar/ >&2
echo " that should be a directory where gzipped 'nix-store --export' ">&2
echo " files are located (they should have .nar.gz extension)" >&2
echo " Or all together: " >&2
echo -e nix-reduce-build /expr.nix /e2.nix -- \\\\\\\n\
" ssh://a@b.example.com http://n.example.com/get-nar?q= file://nar/" >&2
echo " Also supports best-effort local builds of failing expression set:" >&2
echo "nix-reduce-build /e.nix -- nix-daemon:// nix-self://" >&2
echo " nix-daemon:// builds using daemon"
echo " nix-self:// builds directly using nix-store from current installation" >&2
echo " nix-daemon-fixed:// and nix-self-fixed:// do the same, but only for" >&2;
echo "derivations with specified output hash (sha256, sha1 or md5)." >&2
echo " nix-daemon-substitute:// and nix-self-substitute:// try to substitute" >&2;
echo "maximum amount of paths" >&2;
echo " nix-daemon-build:// and nix-self-build:// try to build (not substitute)" >&2;
echo "maximum amount of paths" >&2;
echo " If no package sources are specified, required paths are listed." >&2;
echo nix-reduce-build /etc/nixos/nixos -- user@somewhere.nowhere.example.org >&2
exit;
fi;
@@ -39,14 +19,11 @@ echo Will work on $(cat initial | wc -l) targets. >&2
while read ; do
case "$REPLY" in
${NIX_STORE_DIR:-/nix/store}/*)
${NIX_STORE_PATH:-/nix/store}/*)
echo "$REPLY" >> paths; >&2
;;
*)
(
IFS=: ;
nix-instantiate $REPLY >> paths;
);
nix-instantiate "$REPLY" >> paths;
;;
esac;
done < initial;
@@ -74,94 +51,14 @@ echo Prepared $(cat wanted-paths | wc -l) paths to get. >&2
cat wanted-paths | xargs nix-store --check-validity --print-invalid > needed-paths;
echo We need $(cat needed-paths | wc -l) paths. >&2
egrep '[.]drv$' derivers-closure > critical-derivers;
if test -z "$1" ; then
cat needed-paths;
fi;
refresh_critical_derivers() {
echo "Finding needed derivers..." >&2;
cat critical-derivers | while read; do
if ! (nix-store --query --outputs "$REPLY" | xargs nix-store --check-validity &> /dev/null;); then
echo "$REPLY";
fi;
done > new-critical-derivers;
mv new-critical-derivers critical-derivers;
echo The needed paths are realized by $(cat critical-derivers | wc -l) derivers. >&2
}
build_here() {
cat critical-derivers | while read; do
echo "Realising $REPLY using nix-daemon" >&2
@bindir@/nix-store -r "${REPLY}"
done;
}
try_to_substitute(){
cat needed-paths | while read ; do
echo "Building $REPLY using nix-daemon" >&2
@bindir@/nix-store -r "${NIX_STORE_DIR:-/nix/store}/${REPLY##*/}"
done;
}
for i in "$@"; do
sshHost="${i#ssh://}";
httpHost="${i#http://}";
httpsHost="${i#https://}";
filePath="${i#file:/}";
if [ "$i" != "$sshHost" ]; then
cat needed-paths | while read; do
echo "Getting $REPLY and its closure over ssh" >&2
nix-copy-closure --from "$sshHost" --gzip "$REPLY" </dev/null || true;
done;
elif [ "$i" != "$httpHost" ] || [ "$i" != "$httpsHost" ]; then
cat needed-paths | while read; do
echo "Getting $REPLY over http/https" >&2
curl ${BAD_CERTIFICATE:+-k} -L "$i${REPLY##*/}" | gunzip | nix-store --import;
done;
elif [ "$i" != "$filePath" ] ; then
cat needed-paths | while read; do
echo "Installing $REPLY from file" >&2
gunzip < "$filePath/${REPLY##*/}".nar.gz | nix-store --import;
done;
elif [ "$i" = "nix-daemon://" ] ; then
NIX_REMOTE=daemon try_to_substitute;
refresh_critical_derivers;
NIX_REMOTE=daemon build_here;
elif [ "$i" = "nix-self://" ] ; then
NIX_REMOTE= try_to_substitute;
refresh_critical_derivers;
NIX_REMOTE= build_here;
elif [ "$i" = "nix-daemon-fixed://" ] ; then
refresh_critical_derivers;
cat critical-derivers | while read; do
if egrep '"(md5|sha1|sha256)"' "$REPLY" &>/dev/null; then
echo "Realising $REPLY using nix-daemon" >&2
NIX_REMOTE=daemon @bindir@/nix-store -r "${REPLY}"
fi;
done;
elif [ "$i" = "nix-self-fixed://" ] ; then
refresh_critical_derivers;
cat critical-derivers | while read; do
if egrep '"(md5|sha1|sha256)"' "$REPLY" &>/dev/null; then
echo "Realising $REPLY using direct Nix build" >&2
NIX_REMOTE= @bindir@/nix-store -r "${REPLY}"
fi;
done;
elif [ "$i" = "nix-daemon-substitute://" ] ; then
NIX_REMOTE=daemon try_to_substitute;
elif [ "$i" = "nix-self-substitute://" ] ; then
NIX_REMOTE= try_to_substitute;
elif [ "$i" = "nix-daemon-build://" ] ; then
refresh_critical_derivers;
NIX_REMOTE=daemon build_here;
elif [ "$i" = "nix-self-build://" ] ; then
refresh_critical_derivers;
NIX_REMOTE= build_here;
fi;
cat needed-paths | while read; do
nix-copy-closure --from "$i" --gzip "$REPLY" </dev/null || true;
done;
mv needed-paths wanted-paths;
cat wanted-paths | xargs nix-store --check-validity --print-invalid > needed-paths;
echo We still need $(cat needed-paths | wc -l) paths. >&2

View File

@@ -0,0 +1,88 @@
#! @perl@ -w
# This tool unpacks the closures created by "nix-pack-closure" and
# adds them to the Nix store.
# TODO: make this program "streamy", i.e., don't use a temporary
# directory.
use strict;
use File::Temp qw(tempdir);
my $binDir = $ENV{"NIX_BIN_DIR"};
$binDir = "@bindir@" unless defined $binDir;
my $tmpDir = tempdir("nix-unpack-closure.XXXXXX", CLEANUP => 1, TMPDIR => 1)
or die "cannot create a temporary directory";
# Unpack the NAR archive on standard input.
system("nix-store --restore '$tmpDir/unpacked'") == 0
or die "nix-store --restore failed";
open VALID, ">$tmpDir/validity" or die;
# For each path in the closure that is not yet valid, add it to the
# store. TODO: use proper locking. Or even better, let nix-store do
# this.
opendir(DIR, "$tmpDir/unpacked/contents") or die "cannot open directory: $!";
foreach my $name (sort(readdir DIR)) {
next if $name eq "." or $name eq "..";
my $storePath = "@storedir@/$name"; # !!!
# !!! this really isn't a good validity check!
system "$binDir/nix-store --check-validity '$storePath' 2> /dev/null";
if ($? != 0) {
print STDERR "unpacking `$storePath'...\n";
# !!! race
system("@coreutils@/rm -rf '$storePath'") == 0
or die "cannot remove `$storePath': $?";
system("$binDir/nix-store --restore '$storePath' < '$tmpDir/unpacked/contents/$name'") == 0
or die "nix-store --dump failed on `$storePath': $?";
print VALID "$storePath\n";
open DRV, "<$tmpDir/unpacked/derivers/$name" or die;
my $deriver = <DRV>;
chomp $deriver;
$deriver = "" if $deriver eq "unknown-deriver";
close DRV;
my @refs;
open REFS, "<$tmpDir/unpacked/references/$name" or die;
while (<REFS>) {
chomp;
push @refs, $_;
}
close REFS;
print VALID "$deriver\n";
print VALID (scalar @refs), "\n";
foreach my $ref (@refs) {
print VALID "$ref\n";
}
}
}
closedir(DIR) or die;
# Register the invalid paths as valid.
system("nix-store --register-validity <'$tmpDir/validity'") == 0
or die "nix-store --register-validity failed";
# Show the top-level paths so that something useful can be done with
# them, e.g., passing them to `nix-env -i'.
if (-e "$tmpDir/unpacked/top-level") {
open TOPLEVEL, "<$tmpDir/unpacked/top-level" or die;
while (<TOPLEVEL>) { print "$_"; }
close TOPLEVEL;
}

View File

@@ -2,7 +2,10 @@ use strict;
sub addPatch {
my ($patches, $storePath, $patch) = @_;
my $patches = shift;
my $storePath = shift;
my $patch = shift;
my $allowConflicts = shift;
$$patches{$storePath} = []
unless defined $$patches{$storePath};
@@ -11,9 +14,15 @@ sub addPatch {
my $found = 0;
foreach my $patch2 (@{$patchList}) {
$found = 1 if
$patch2->{url} eq $patch->{url} &&
$patch2->{basePath} eq $patch->{basePath};
if ($patch2->{url} eq $patch->{url}) {
if ($patch2->{hash} eq $patch->{hash}) {
$found = 1 if ($patch2->{basePath} eq $patch->{basePath});
} else {
die "conflicting hashes for URL $patch->{url}, " .
"namely $patch2->{hash} and $patch->{hash}"
unless $allowConflicts;
}
}
}
push @{$patchList}, $patch if !$found;
@@ -23,7 +32,12 @@ sub addPatch {
sub readManifest {
my ($manifest, $narFiles, $localPaths, $patches) = @_;
my $manifest = shift;
my $narFiles = shift;
my $localPaths = shift;
my $patches = shift;
my $allowConflicts = shift;
$allowConflicts = 0 unless defined $allowConflicts;
open MANIFEST, "<$manifest"
or die "cannot open `$manifest': $!";
@@ -84,7 +98,15 @@ sub readManifest {
my $found = 0;
foreach my $narFile (@{$narFileList}) {
$found = 1 if $narFile->{url} eq $url;
if ($narFile->{url} eq $url) {
if ($narFile->{hash} eq $hash) {
$found = 1;
} else {
die "conflicting hashes for URL $url, " .
"namely $narFile->{hash} and $hash"
unless $allowConflicts;
}
}
}
if (!$found) {
push @{$narFileList},
@@ -102,7 +124,7 @@ sub readManifest {
, basePath => $basePath, baseHash => $baseHash
, narHash => $narHash, patchType => $patchType
, hashAlgo => $hashAlgo
};
}, $allowConflicts;
}
elsif ($type eq "localPath") {
@@ -149,8 +171,12 @@ sub readManifest {
}
sub writeManifest {
my ($manifest, $narFiles, $patches) = @_;
sub writeManifest
{
my $manifest = shift;
my $narFiles = shift;
my $patches = shift;
my $copySources = shift;
open MANIFEST, ">$manifest.tmp"; # !!! check exclusive
@@ -164,9 +190,9 @@ sub writeManifest {
print MANIFEST "{\n";
print MANIFEST " StorePath: $storePath\n";
print MANIFEST " NarURL: $narFile->{url}\n";
print MANIFEST " Hash: $narFile->{hash}\n" if defined $narFile->{hash};
print MANIFEST " Hash: $narFile->{hash}\n";
print MANIFEST " NarHash: $narFile->{narHash}\n";
print MANIFEST " Size: $narFile->{size}\n" if defined $narFile->{size};
print MANIFEST " Size: $narFile->{size}\n";
print MANIFEST " References: $narFile->{references}\n"
if defined $narFile->{references} && $narFile->{references} ne "";
print MANIFEST " Deriver: $narFile->{deriver}\n"

View File

@@ -1,5 +1,5 @@
SUBDIRS = bin2c boost libutil libstore libmain nix-store nix-hash \
SUBDIRS = bin2c boost libutil libext3cow libstore libmain nix-store nix-hash \
libexpr nix-instantiate nix-env nix-worker nix-setuid-helper \
nix-log2xml bsdiff-4.3
nix-log2xml bsdiff-4.3 nix-state
EXTRA_DIST = aterm-helper.pl

View File

@@ -1,6 +1,6 @@
SUBDIRS = format
nobase_pkginclude_HEADERS = assert.hpp checked_delete.hpp format.hpp \
pkginclude_HEADERS = assert.hpp checked_delete.hpp format.hpp \
shared_ptr.hpp weak_ptr.hpp throw_exception.hpp \
enable_shared_from_this.hpp \
detail/shared_count.hpp detail/workaround.hpp

View File

@@ -2,13 +2,11 @@ pkglib_LTLIBRARIES = libexpr.la
libexpr_la_SOURCES = \
nixexpr.cc eval.cc primops.cc lexer-tab.cc parser-tab.cc \
get-drvs.cc attr-path.cc expr-to-xml.cc common-opts.cc \
names.cc
get-drvs.cc attr-path.cc expr-to-xml.cc common-opts.cc
pkginclude_HEADERS = \
nixexpr.hh eval.hh parser.hh lexer-tab.hh parser-tab.hh \
get-drvs.hh attr-path.hh expr-to-xml.hh common-opts.hh \
names.hh nixexpr-ast.hh
get-drvs.hh attr-path.hh expr-to-xml.hh common-opts.hh
libexpr_la_LIBADD = ../libutil/libutil.la ../libstore/libstore.la \
../boost/format/libformat.la
@@ -19,7 +17,7 @@ BUILT_SOURCES = nixexpr-ast.cc nixexpr-ast.hh \
EXTRA_DIST = lexer.l parser.y nixexpr-ast.def nixexpr-ast.cc
AM_CXXFLAGS = \
-I$(srcdir)/.. ${aterm_include} \
-I$(srcdir)/.. ${bdb_include} ${aterm_include} \
-I$(srcdir)/../libutil -I$(srcdir)/../libstore
AM_CFLAGS = \
${aterm_include}

View File

@@ -23,8 +23,6 @@ EvalState::EvalState()
initNixExprHelpers();
addPrimOps();
allowUnsafeEquality = getEnv("NIX_NO_UNSAFE_EQ", "") == "";
}
@@ -50,11 +48,6 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2))
throw EvalError(format(s) % s2);
}
LocalNoInlineNoReturn(void throwTypeError(const char * s))
{
throw TypeError(s);
}
LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s2))
{
throw TypeError(format(s) % s2);
@@ -76,91 +69,77 @@ LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2,
}
/* Pattern-match `pat' against `arg'. The result is a set of
substitutions (`subs') and a set of recursive substitutions
(`subsRecursive'). The latter can refer to the variables bound by
both `subs' and `subsRecursive'. */
static void patternMatch(EvalState & state,
Pattern pat, Expr arg, ATermMap & subs, ATermMap & subsRecursive)
{
ATerm name;
ATermList formals;
Pattern pat1, pat2;
ATermBool ellipsis;
if (matchVarPat(pat, name))
subs.set(name, arg);
else if (matchAttrsPat(pat, formals, ellipsis)) {
arg = evalExpr(state, arg);
/* Get the actual arguments. */
ATermMap attrs;
queryAllAttrs(arg, attrs);
unsigned int nrAttrs = attrs.size();
/* For each formal argument, get the actual argument. If
there is no matching actual argument but the formal
argument has a default, use the default. */
unsigned int attrsUsed = 0;
for (ATermIterator i(formals); i; ++i) {
Expr name, def;
DefaultValue def2;
if (!matchFormal(*i, name, def2)) abort(); /* can't happen */
Expr value = attrs[name];
if (value == 0) {
if (!matchDefaultValue(def2, def)) def = 0;
if (def == 0) throw TypeError(format("the argument named `%1%' required by the function is missing")
% aterm2String(name));
subsRecursive.set(name, def);
} else {
attrsUsed++;
attrs.remove(name);
subs.set(name, value);
}
}
/* Check that each actual argument is listed as a formal
argument (unless the attribute match specifies a `...'). */
if (ellipsis == eFalse && attrsUsed != nrAttrs)
throw TypeError(format("the function does not expect an argument named `%1%'")
% aterm2String(attrs.begin()->key));
}
else if (matchAtPat(pat, pat1, pat2)) {
patternMatch(state, pat1, arg, subs, subsRecursive);
patternMatch(state, pat2, arg, subs, subsRecursive);
}
else abort();
}
/* Substitute an argument set into the body of a function. */
static Expr substArgs(EvalState & state,
Expr body, Pattern pat, Expr arg)
Expr body, ATermList formals, Expr arg)
{
ATermMap subs(16), subsRecursive(16);
patternMatch(state, pat, arg, subs, subsRecursive);
unsigned int nrFormals = ATgetLength(formals);
ATermMap subs(nrFormals);
/* If we used any default values, make a recursive attribute set
out of the (argument-name, value) tuples. This is so that we
can support default values that refer to each other, e.g. ({x,
y ? x + x}: y) {x = "foo";} evaluates to "foofoo". */
if (subsRecursive.size() != 0) {
ATermList recAttrs = ATempty;
foreach (ATermMap::const_iterator, i, subs)
recAttrs = ATinsert(recAttrs, makeBind(i->key, i->value, makeNoPos()));
foreach (ATermMap::const_iterator, i, subsRecursive)
/* Get the actual arguments and put them in the substitution. */
ATermMap args;
queryAllAttrs(arg, args);
for (ATermMap::const_iterator i = args.begin(); i != args.end(); ++i)
subs.set(i->key, i->value);
/* Get the formal arguments. */
ATermVector defsUsed;
ATermList recAttrs = ATempty;
for (ATermIterator i(formals); i; ++i) {
Expr name, def;
ValidValues valids2;
DefaultValue def2;
if (!matchFormal(*i, name, valids2, def2)) abort(); /* can't happen */
Expr value = subs[name];
if (value == 0) {
if (!matchDefaultValue(def2, def)) def = 0;
if (def == 0) throw TypeError(format("the argument named `%1%' required by the function is missing")
% aterm2String(name));
value = def;
defsUsed.push_back(name);
recAttrs = ATinsert(recAttrs, makeBind(name, def, makeNoPos()));
}
ATermList valids;
if (matchValidValues(valids2, valids)) {
value = evalExpr(state, value);
bool found = false;
for (ATermIterator j(valids); j; ++j) {
Expr v = evalExpr(state, *j);
if (value == v) {
found = true;
break;
}
}
if (!found) throw TypeError(format("the argument named `%1%' has an illegal value")
% aterm2String(name));
}
}
/* Make a recursive attribute set out of the (argument-name,
value) tuples. This is so that we can support default
parameters that refer to each other, e.g. ({x, y ? x + x}: y)
{x = "foo";} evaluates to "foofoo". */
if (defsUsed.size() != 0) {
for (ATermMap::const_iterator i = args.begin(); i != args.end(); ++i)
recAttrs = ATinsert(recAttrs, makeBind(i->key, i->value, makeNoPos()));
Expr rec = makeRec(recAttrs, ATempty);
foreach (ATermMap::const_iterator, i, subsRecursive)
subs.set(i->key, makeSelect(rec, i->key));
for (ATermVector::iterator i = defsUsed.begin(); i != defsUsed.end(); ++i)
subs.set(*i, makeSelect(rec, *i));
}
if (subs.size() != nrFormals) {
/* One or more actual arguments were not declared as formal
arguments. Find out which. */
for (ATermIterator i(formals); i; ++i) {
Expr name; ATerm d1, d2;
if (!matchFormal(*i, name, d1, d2)) abort();
subs.remove(name);
}
throw TypeError(format("the function does not expect an argument named `%1%'")
% aterm2String(subs.begin()->key));
}
return substitute(Substitution(0, &subs), body);
@@ -172,12 +151,11 @@ static Expr substArgs(EvalState & state,
to attributes substituted with selection expressions on the
original set. E.g., e = `rec {x = f x y; y = x;}' becomes `{x = f
(e.x) (e.y); y = e.x;}'. */
LocalNoInline(ATerm expandRec(EvalState & state, ATerm e, ATermList rbnds, ATermList nrbnds))
LocalNoInline(ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds))
{
ATerm name;
Expr e2;
Pos pos;
Expr eOverrides = 0;
/* Create the substitution list. */
ATermMap subs(ATgetLength(rbnds) + ATgetLength(nrbnds));
@@ -187,26 +165,9 @@ LocalNoInline(ATerm expandRec(EvalState & state, ATerm e, ATermList rbnds, ATerm
}
for (ATermIterator i(nrbnds); i; ++i) {
if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
if (name == sOverrides) eOverrides = e2;
subs.set(name, e2);
}
/* If the rec contains an attribute called `__overrides', then
evaluate it, and add the attributes in that set to the rec.
This allows overriding of recursive attributes, which is
otherwise not possible. (You can use the // operator to
replace an attribute, but other attributes in the rec will
still reference the original value, because that value has been
substituted into the bodies of the other attributes. Hence we
need __overrides.) */
ATermMap overrides;
if (eOverrides) {
eOverrides = evalExpr(state, eOverrides);
queryAllAttrs(eOverrides, overrides, false);
foreach (ATermMap::const_iterator, i, overrides)
subs.set(i->key, i->value);
}
Substitution subs_(0, &subs);
/* Create the non-recursive set. */
@@ -216,10 +177,6 @@ LocalNoInline(ATerm expandRec(EvalState & state, ATerm e, ATermList rbnds, ATerm
as.set(name, makeAttrRHS(substitute(subs_, e2), pos));
}
if (eOverrides)
foreach (ATermMap::const_iterator, i, overrides)
as.set(i->key, makeAttrRHS(i->value, makeNoPos()));
/* Copy the non-recursive bindings. !!! inefficient */
for (ATermIterator i(nrbnds); i; ++i) {
if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
@@ -242,7 +199,7 @@ LocalNoInline(Expr updateAttrs(Expr e1, Expr e2))
}
string evalString(EvalState & state, Expr e, ATermList & context)
string evalString(EvalState & state, Expr e, PathSet & context)
{
e = evalExpr(state, e);
string s;
@@ -254,10 +211,11 @@ string evalString(EvalState & state, Expr e, ATermList & context)
string evalStringNoCtx(EvalState & state, Expr e)
{
ATermList context;
PathSet context;
string s = evalString(state, e, context);
if (context != ATempty)
throw EvalError(format("the string `%1%' is not allowed to refer to a store path") % s);
if (!context.empty())
throw EvalError(format("the string `%1%' is not allowed to refer to a store path (such as `%2%')")
% s % *(context.begin()));
return s;
}
@@ -311,7 +269,7 @@ ATermList flattenList(EvalState & state, Expr e)
}
string coerceToString(EvalState & state, Expr e, Context & context,
string coerceToString(EvalState & state, Expr e, PathSet & context,
bool coerceMore, bool copyToStore)
{
e = evalExpr(state, e);
@@ -342,22 +300,14 @@ string coerceToString(EvalState & state, Expr e, Context & context,
% path % dstPath);
}
context.set(toATerm(dstPath), makeNull());
context.insert(dstPath);
return dstPath;
}
ATermList es;
if (matchAttrs(e, es)) {
Expr e2 = queryAttr(e, "outPath");
if (!e2) throwTypeError("cannot coerce an attribute set (except a derivation) to a string");
/* !!! hacky */
ATermList c;
string s = evalString(state, e2, c);
Context c2; matchContext(c, c2);
foreach (Context::const_iterator, i, c2)
context.set(i->key, e);
return s;
}
if (matchAttrs(e, es))
return coerceToString(state, makeSelect(e, toATerm("outPath")),
context, coerceMore, copyToStore);
if (coerceMore) {
@@ -390,9 +340,9 @@ string coerceToString(EvalState & state, Expr e, Context & context,
static ATerm concatStrings(EvalState & state, ATermVector & args,
string separator = "")
{
if (args.empty()) return makeStr("", ATempty);
if (args.empty()) return makeStr("", PathSet());
Context context;
PathSet context;
std::ostringstream s;
/* If the first element is a path, then the result will also be a
@@ -408,7 +358,7 @@ static ATerm concatStrings(EvalState & state, ATermVector & args,
s << coerceToString(state, *i, context, false, !isPath);
}
if (isPath && context.size() != 0)
if (isPath && !context.empty())
throw EvalError(format("a string that refers to a store path cannot be appended to a path, in `%1%'")
% s.str());
@@ -418,7 +368,7 @@ static ATerm concatStrings(EvalState & state, ATermVector & args,
}
Path coerceToPath(EvalState & state, Expr e, Context & context)
Path coerceToPath(EvalState & state, Expr e, PathSet & context)
{
string path = coerceToString(state, e, context, false, false);
if (path == "" || path[0] != '/')
@@ -429,18 +379,15 @@ Path coerceToPath(EvalState & state, Expr e, Context & context)
Expr autoCallFunction(Expr e, const ATermMap & args)
{
Pattern pat;
ATerm body, pos;
ATermList formals;
ATermBool ellipsis;
ATerm body, pos;
/* !!! this should be more general */
if (matchFunction(e, pat, body, pos) && matchAttrsPat(pat, formals, ellipsis)) {
if (matchFunction(e, formals, body, pos)) {
ATermMap actualArgs(ATgetLength(formals));
for (ATermIterator i(formals); i; ++i) {
Expr name, def, value; ATerm def2;
if (!matchFormal(*i, name, def2)) abort();
Expr name, def, value; ATerm values, def2;
if (!matchFormal(*i, name, values, def2)) abort();
if ((value = args.get(name)))
actualArgs.set(name, makeAttrRHS(value, makeNoPos()));
else if (!matchDefaultValue(def2, def))
@@ -480,8 +427,8 @@ LocalNoInline(Expr evalVar(EvalState & state, ATerm name))
LocalNoInline(Expr evalCall(EvalState & state, Expr fun, Expr arg))
{
Pattern pat;
ATerm pos;
ATermList formals;
ATerm pos, name;
Expr body;
/* Evaluate the left-hand side. */
@@ -507,9 +454,10 @@ LocalNoInline(Expr evalCall(EvalState & state, Expr fun, Expr arg))
return makePrimOp(arity, funBlob, args);
}
else if (matchFunction(fun, pat, body, pos)) {
else if (matchFunction(fun, formals, body, pos)) {
arg = evalExpr(state, arg);
try {
return evalExpr(state, substArgs(state, body, pat, arg));
return evalExpr(state, substArgs(state, body, formals, arg));
} catch (Error & e) {
addErrorPrefix(e, "while evaluating the function at %1%:\n",
showPos(pos));
@@ -517,6 +465,18 @@ LocalNoInline(Expr evalCall(EvalState & state, Expr fun, Expr arg))
}
}
else if (matchFunction1(fun, name, body, pos)) {
try {
ATermMap subs(1);
subs.set(name, arg);
return evalExpr(state, substitute(Substitution(0, &subs), body));
} catch (Error & e) {
addErrorPrefix(e, "while evaluating the function at %1%:\n",
showPos(pos));
throw;
}
}
else throwTypeError(
"attempt to call something which is neither a function nor a primop (built-in operation) but %1%",
showType(fun));
@@ -605,7 +565,7 @@ LocalNoInline(Expr evalPlusConcat(EvalState & state, Expr e))
"concatenation of a derivation and a path is deprecated; "
"you should write `drv + \"%1%\"' instead of `drv + %1%'")
% aterm2String(p));
Context context;
PathSet context;
return makeStr(
coerceToString(state, makeSelect(e1, toATerm("outPath")), context)
+ aterm2String(p), context);
@@ -651,48 +611,6 @@ LocalNoInline(Expr evalOpConcat(EvalState & state, Expr e1, Expr e2))
}
/* Implementation of the `==' and `!=' operators. */
LocalNoInline(bool areEqual(EvalState & state, Expr e1, Expr e2))
{
e1 = evalExpr(state, e1);
e2 = evalExpr(state, e2);
/* We cannot test functions/primops for equality, and we currently
don't support testing equality between attribute sets or lists
- that would have to be a deep equality test to be sound. */
AFun sym1 = ATgetAFun(e1);
AFun sym2 = ATgetAFun(e2);
if (sym1 != sym2) return false;
/* Functions are incomparable. */
if (sym1 == symFunction || sym1 == symPrimOp) return false;
if (!state.allowUnsafeEquality && sym1 == symAttrs)
throw EvalError("comparison of attribute sets is not implemented");
/* !!! This allows comparisons of infinite data structures to
succeed, such as `let x = [x]; in x == x'. This is
undesirable, since equivalent (?) terms such as `let x = [x]; y
= [y]; in x == y' don't terminate. */
if (e1 == e2) return true;
if (sym1 == symList) {
ATermList es1; matchList(e1, es1);
ATermList es2; matchList(e2, es2);
if (ATgetLength(es1) != ATgetLength(es2)) return false;
ATermIterator i(es1), j(es2);
while (*i) {
if (!areEqual(state, *i, *j)) return false;
++i; ++j;
}
return true;
}
return false;
}
static char * deepestStack = (char *) -1; /* for measuring stack usage */
@@ -715,6 +633,7 @@ Expr evalExpr2(EvalState & state, Expr e)
sym == symInt ||
sym == symBool ||
sym == symFunction ||
sym == symFunction1 ||
sym == symAttrs ||
sym == symList ||
sym == symPrimOp)
@@ -738,7 +657,7 @@ Expr evalExpr2(EvalState & state, Expr e)
/* Mutually recursive sets. */
ATermList rbnds, nrbnds;
if (matchRec(e, rbnds, nrbnds))
return expandRec(state, e, rbnds, nrbnds);
return expandRec(e, rbnds, nrbnds);
/* Conditionals. */
if (matchIf(e, e1, e2, e3))
@@ -756,10 +675,12 @@ Expr evalExpr2(EvalState & state, Expr e)
However, we don't want to make (==) strict, because that would
make operations like `big_derivation == null' very slow (unless
we were to evaluate them side-by-side). */
if (matchOpEq(e, e1, e2)) return makeBool(areEqual(state, e1, e2));
if (matchOpNEq(e, e1, e2)) return makeBool(!areEqual(state, e1, e2));
if (matchOpEq(e, e1, e2))
return makeBool(evalExpr(state, e1) == evalExpr(state, e2));
if (matchOpNEq(e, e1, e2))
return makeBool(evalExpr(state, e1) != evalExpr(state, e2));
/* Negation. */
if (matchOpNot(e, e1))
return makeBool(!evalBool(state, e1));
@@ -872,6 +793,29 @@ static Expr strictEvalExpr_(EvalState & state, Expr e, ATermMap & nfs)
return makeList(ATreverse(es2));
}
ATermList formals;
ATerm body, pos;
if (matchFunction(e, formals, body, pos)) {
ATermList formals2 = ATempty;
for (ATermIterator i(formals); i; ++i) {
Expr name; ValidValues valids; ATerm dummy;
if (!matchFormal(*i, name, valids, dummy)) abort();
ATermList valids2;
if (matchValidValues(valids, valids2)) {
ATermList valids3 = ATempty;
for (ATermIterator j(valids2); j; ++j)
valids3 = ATinsert(valids3, strictEvalExpr(state, *j, nfs));
valids = makeValidValues(ATreverse(valids3));
}
formals2 = ATinsert(formals2, makeFormal(name, valids, dummy));
}
return makeFunction(ATreverse(formals2), body, pos);
}
return e;
}

View File

@@ -16,7 +16,7 @@ class Hash;
typedef std::map<Path, PathSet> DrvRoots;
typedef std::map<Path, Hash> DrvHashes;
/* Cache for calls to addToStore(); maps source paths to the store
/* Cache for calls to addToStore(); maps source paths to the store //THIS OK ????
paths. */
typedef std::map<Path, Path> SrcToStore;
@@ -38,8 +38,6 @@ struct EvalState
unsigned int nrEvaluated;
unsigned int nrCached;
bool allowUnsafeEquality;
EvalState();
void addPrimOps();
@@ -61,7 +59,7 @@ Expr evalFile(EvalState & state, const Path & path);
Expr strictEvalExpr(EvalState & state, Expr e);
/* Specific results. */
string evalString(EvalState & state, Expr e, ATermList & context);
string evalString(EvalState & state, Expr e, PathSet & context);
string evalStringNoCtx(EvalState & state, Expr e);
int evalInt(EvalState & state, Expr e);
bool evalBool(EvalState & state, Expr e);
@@ -74,13 +72,13 @@ ATermList flattenList(EvalState & state, Expr e);
/* String coercion. Converts strings, paths and derivations to a
string. If `coerceMore' is set, also converts nulls, integers,
booleans and lists to a string. */
string coerceToString(EvalState & state, Expr e, Context & context,
string coerceToString(EvalState & state, Expr e, PathSet & context,
bool coerceMore = false, bool copyToStore = true);
/* Path coercion. Converts strings, paths and derivations to a path.
The result is guaranteed to be an canonicalised, absolute path.
Nothing is copied to the store. */
Path coerceToPath(EvalState & state, Expr e, Context & context);
Path coerceToPath(EvalState & state, Expr e, PathSet & context);
/* Automatically call a function for which each argument has a default
value or has a binding in the `args' map. Note: result is a call,

View File

@@ -4,8 +4,6 @@
#include "aterm.hh"
#include "util.hh"
#include <cstdlib>
namespace nix {
@@ -23,12 +21,12 @@ static XMLAttrs singletonAttrs(const string & name, const string & value)
typedef set<Expr> ExprSet;
static void printTermAsXML(Expr e, XMLWriter & doc, Context & context,
static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context,
ExprSet & drvsSeen);
static void showAttrs(const ATermMap & attrs, XMLWriter & doc,
Context & context, ExprSet & drvsSeen)
PathSet & context, ExprSet & drvsSeen)
{
StringSet names;
for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i)
@@ -40,40 +38,15 @@ static void showAttrs(const ATermMap & attrs, XMLWriter & doc,
}
static void printPatternAsXML(Pattern pat, XMLWriter & doc)
{
ATerm name;
ATermList formals;
Pattern pat1, pat2;
ATermBool ellipsis;
if (matchVarPat(pat, name))
doc.writeEmptyElement("varpat", singletonAttrs("name", aterm2String(name)));
else if (matchAttrsPat(pat, formals, ellipsis)) {
XMLOpenElement _(doc, "attrspat");
for (ATermIterator i(formals); i; ++i) {
Expr name; ATerm dummy;
if (!matchFormal(*i, name, dummy)) abort();
doc.writeEmptyElement("attr", singletonAttrs("name", aterm2String(name)));
}
if (ellipsis == eTrue) doc.writeEmptyElement("ellipsis");
}
else if (matchAtPat(pat, pat1, pat2)) {
XMLOpenElement _(doc, "at");
printPatternAsXML(pat1, doc);
printPatternAsXML(pat2, doc);
}
}
static void printTermAsXML(Expr e, XMLWriter & doc, Context & context,
static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context,
ExprSet & drvsSeen)
{
XMLAttrs attrs;
string s;
ATerm s2;
int i;
ATermList as, es;
ATerm pat, body, pos;
ATermList as, es, formals;
ATerm body, pos;
checkInterrupt();
@@ -134,9 +107,22 @@ static void printTermAsXML(Expr e, XMLWriter & doc, Context & context,
printTermAsXML(*i, doc, context, drvsSeen);
}
else if (matchFunction(e, pat, body, pos)) {
else if (matchFunction(e, formals, body, pos)) {
XMLOpenElement _(doc, "function");
printPatternAsXML(pat, doc);
for (ATermIterator i(formals); i; ++i) {
Expr name; ValidValues valids; ATerm dummy;
if (!matchFormal(*i, name, valids, dummy)) abort();
XMLOpenElement _(doc, "arg", singletonAttrs("name", aterm2String(name)));
ATermList valids2;
if (matchValidValues(valids, valids2)) {
for (ATermIterator j(valids2); j; ++j) {
XMLOpenElement _(doc, "value");
printTermAsXML(*j, doc, context, drvsSeen);
}
}
}
}
else
@@ -144,7 +130,7 @@ static void printTermAsXML(Expr e, XMLWriter & doc, Context & context,
}
void printTermAsXML(Expr e, std::ostream & out, Context & context)
void printTermAsXML(Expr e, std::ostream & out, PathSet & context)
{
XMLWriter doc(true, out);
XMLOpenElement root(doc, "expr");

View File

@@ -9,7 +9,7 @@
namespace nix {
void printTermAsXML(Expr e, std::ostream & out, Context & context);
void printTermAsXML(Expr e, std::ostream & out, PathSet & context);
}

View File

@@ -17,7 +17,7 @@ string DrvInfo::queryDrvPath(EvalState & state) const
if (a && matchPath(evalExpr(state, a), t))
return aterm2String(t);
Context context;
PathSet context;
(string &) drvPath = a ? coerceToPath(state, a, context) : "";
}
return drvPath;
@@ -29,12 +29,59 @@ string DrvInfo::queryOutPath(EvalState & state) const
if (outPath == "") {
Expr a = attrs->get(toATerm("outPath"));
if (!a) throw TypeError("output path missing");
Context context;
PathSet context;
(string &) outPath = coerceToPath(state, a, context);
}
return outPath;
}
string DrvInfo::queryStateIdentifier(EvalState & state) const
{
if (stateIdentifier == "") {
ATermMap attrs2 = *attrs;
for (ATermMap::const_iterator i = attrs2.begin(); i != attrs2.end(); ++i) {
string key = (string)aterm2String(i->key); //cast because aterm2String returns a char*
//printMsg(lvlError, format("ATTR2: '%1%'") % key);
if(key == "stateIdentifier"){
PathSet context;
string value = coerceToString(state, i->value, context);
(string &) stateIdentifier = value;
}
}
//If still empty
if (trim(stateIdentifier) == "")
(string &) stateIdentifier = "__NOSTATE__";
}
return stateIdentifier;
}
string DrvInfo::queryRuntimeStateArgs(EvalState & state) const
{
if (runtimeStateArgs == "") {
ATermMap attrs2 = *attrs;
for (ATermMap::const_iterator i = attrs2.begin(); i != attrs2.end(); ++i) {
string key = (string)aterm2String(i->key); //cast because aterm2String returns a char*
if(key == "runtimeStateArgs"){
PathSet context;
string value = coerceToString(state, i->value, context);
(string &) runtimeStateArgs = value;
}
}
//If still empty
if (trim(runtimeStateArgs) == "")
(string &) runtimeStateArgs = "__NOARGS__";
}
return runtimeStateArgs;
}
MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
{
@@ -49,56 +96,32 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
for (ATermMap::const_iterator i = attrs2.begin(); i != attrs2.end(); ++i) {
Expr e = evalExpr(state, i->value);
string s;
ATermList context;
MetaValue value;
int n;
ATermList es;
if (matchStr(e, s, context)) {
value.type = MetaValue::tpString;
value.stringValue = s;
meta[aterm2String(i->key)] = value;
} else if (matchInt(e, n)) {
value.type = MetaValue::tpInt;
value.intValue = n;
meta[aterm2String(i->key)] = value;
} else if (matchList(e, es)) {
value.type = MetaValue::tpStrings;
for (ATermIterator j(es); j; ++j)
value.stringValues.push_back(evalStringNoCtx(state, *j));
meta[aterm2String(i->key)] = value;
}
PathSet context;
if (matchStr(e, s, context))
meta[aterm2String(i->key)] = s;
/* For future compatibility, ignore attribute values that are
not strings. */
}
return meta;
}
MetaValue DrvInfo::queryMetaInfo(EvalState & state, const string & name) const
string DrvInfo::queryMetaInfo(EvalState & state, const string & name) const
{
/* !!! evaluates all meta attributes => inefficient */
return queryMetaInfo(state)[name];
MetaInfo meta = queryMetaInfo(state);
MetaInfo::iterator i = meta.find(name);
return i == meta.end() ? "" : i->second;
}
void DrvInfo::setMetaInfo(const MetaInfo & meta)
{
ATermMap metaAttrs;
foreach (MetaInfo::const_iterator, i, meta) {
Expr e;
switch (i->second.type) {
case MetaValue::tpInt: e = makeInt(i->second.intValue); break;
case MetaValue::tpString: e = makeStr(i->second.stringValue); break;
case MetaValue::tpStrings: {
ATermList es = ATempty;
foreach (Strings::const_iterator, j, i->second.stringValues)
es = ATinsert(es, makeStr(*j));
e = makeList(ATreverse(es));
break;
}
default: abort();
}
metaAttrs.set(toATerm(i->first), makeAttrRHS(e, makeNoPos()));
}
for (MetaInfo::const_iterator i = meta.begin(); i != meta.end(); ++i)
metaAttrs.set(toATerm(i->first),
makeAttrRHS(makeStr(i->second), makeNoPos()));
attrs->set(toATerm("meta"), makeAttrs(metaAttrs));
}
@@ -126,20 +149,23 @@ static bool getDerivation(EvalState & state, Expr e,
boost::shared_ptr<ATermMap> attrs(new ATermMap());
queryAllAttrs(e, *attrs, false);
Expr a = attrs->get(toATerm("type"));
if (!a || evalStringNoCtx(state, a) != "derivation") return true;
if (!a || evalStringNoCtx(state, a) != "derivation")
return true;
/* Remove spurious duplicates (e.g., an attribute set like
`rec { x = derivation {...}; y = x;}'. */
if (doneExprs.find(e) != doneExprs.end()) return false;
if (doneExprs.find(e) != doneExprs.end())
return false;
doneExprs.insert(e);
DrvInfo drv;
a = attrs->get(toATerm("name"));
/* !!! We really would like to have a decent back trace here. */
if (!a) throw TypeError("derivation name missing");
if (!a)
throw TypeError("derivation name missing");
drv.name = evalStringNoCtx(state, a);
a = attrs->get(toATerm("system"));
@@ -149,7 +175,9 @@ static bool getDerivation(EvalState & state, Expr e,
drv.system = evalStringNoCtx(state, a);
drv.attrs = attrs;
//printMsg(lvlError, format("TEST '%1%'") % evalStringNoCtx(state, a) );
drv.attrPath = attrPath;
drvs.push_back(drv);
@@ -166,7 +194,8 @@ bool getDerivation(EvalState & state, Expr e, DrvInfo & drv)
Exprs doneExprs;
DrvInfos drvs;
getDerivation(state, e, "", drvs, doneExprs);
if (drvs.size() != 1) return false;
if (drvs.size() != 1)
return false;
drv = drvs.front();
return true;
}
@@ -197,30 +226,24 @@ static void getDerivations(EvalState & state, Expr e,
/* !!! undocumented hackery to support combining channels in
nix-env.cc. */
bool combineChannels = drvMap.get(toATerm("_combineChannels"));
/* Consider the attributes in sorted order to get more
deterministic behaviour in nix-env operations (e.g. when
there are names clashes between derivations, the derivation
bound to the attribute with the "lower" name should take
precedence). */
typedef std::map<string, Expr> AttrsSorted;
AttrsSorted attrsSorted;
foreach (ATermMap::const_iterator, i, drvMap)
attrsSorted[aterm2String(i->key)] = i->value;
foreach (AttrsSorted::iterator, i, attrsSorted) {
startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first);
string pathPrefix2 = addToPath(pathPrefix, i->first);
if (combineChannels)
getDerivations(state, i->second, pathPrefix2, autoArgs, drvs, doneExprs);
else if (getDerivation(state, i->second, pathPrefix2, drvs, doneExprs)) {
Expr e2 = drvMap.get(toATerm("_combineChannels"));
bool combineChannels = e2 && evalBool(state, e2);
for (ATermMap::const_iterator i = drvMap.begin(); i != drvMap.end(); ++i) {
startNest(nest, lvlDebug,
format("evaluating attribute `%1%'") % aterm2String(i->key));
string pathPrefix2 = addToPath(pathPrefix, aterm2String(i->key));
if (combineChannels) {
if (((string) aterm2String(i->key)) != "_combineChannels")
getDerivations(state, i->value, pathPrefix2, autoArgs, drvs, doneExprs);
}
else if (getDerivation(state, i->value, pathPrefix2, drvs, doneExprs)) {
/* If the value of this attribute is itself an
attribute set, should we recurse into it? => Only
if it has a `recurseForDerivations = true'
attribute. */
ATermList es;
Expr e = evalExpr(state, i->second), e2;
Expr e = evalExpr(state, i->value);
if (matchAttrs(e, es)) {
ATermMap attrs(ATgetLength(es));
queryAllAttrs(e, attrs, false);

View File

@@ -12,16 +12,7 @@
namespace nix {
struct MetaValue
{
enum { tpNone, tpString, tpStrings, tpInt } type;
string stringValue;
Strings stringValues;
int intValue;
};
typedef std::map<string, MetaValue> MetaInfo;
typedef std::map<string, string> MetaInfo;
struct DrvInfo
@@ -29,6 +20,8 @@ struct DrvInfo
private:
string drvPath;
string outPath;
string stateIdentifier;
string runtimeStateArgs;
public:
string name;
@@ -42,8 +35,10 @@ public:
string queryDrvPath(EvalState & state) const;
string queryOutPath(EvalState & state) const;
string queryStateIdentifier(EvalState & state) const;
string queryRuntimeStateArgs(EvalState & state) const;
MetaInfo queryMetaInfo(EvalState & state) const;
MetaValue queryMetaInfo(EvalState & state, const string & name) const;
string queryMetaInfo(EvalState & state, const string & name) const;
void setDrvPath(const string & s)
{
@@ -54,7 +49,17 @@ public:
{
outPath = s;
}
void setStateIdentifier(const string & s)
{
stateIdentifier = s;
}
void setRuntimeStateArgs(const string & s)
{
runtimeStateArgs = s;
}
void setMetaInfo(const MetaInfo & meta);
};

View File

@@ -95,7 +95,6 @@ let { return LET; }
in { return IN; }
rec { return REC; }
inherit { return INHERIT; }
\.\.\. { return ELLIPSIS; }
\=\= { return EQ; }
\!\= { return NEQ; }

View File

@@ -1,13 +1,10 @@
%% Note: this SDF grammar is no longer used in the Nix expression
%% parser and may not be up to date.
definition
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Top level syntax.
module Main
module Nix
imports Nix-Exprs Nix-Layout
@@ -41,7 +38,6 @@ exports
"with" Expr ";" Expr -> Expr {cons("With")}
"rec" "{" Bind* "}" -> Expr {cons("Rec")}
"let" Bind* "in" Expr -> Expr {cons("Let")}
"let" "{" Bind* "}" -> Expr {cons("LetRec")}
"{" Bind* "}" -> Expr {cons("Attrs")}
@@ -106,8 +102,7 @@ exports
[0-9]+ -> Int
"\"" (~[\"\\] | ("\\" ~[]) )* "\"" -> Str
"''" (~[\"\\] | ("\\" ~[]) )* "''" -> Str
"\"" ~[\n\"]* "\"" -> Str
[a-zA-Z0-9\.\_\-\+]* ("/"[a-zA-Z0-9\.\_\-\+]+)+ -> Path

View File

@@ -3,7 +3,8 @@ init initNixExprHelpers
Pos | string int int | Pos |
NoPos | | Pos |
Function | Pattern Expr Pos | Expr |
Function | ATermList Expr Pos | Expr |
Function1 | string Expr Pos | Expr |
Assert | Expr Expr Pos | Expr |
With | Expr Expr Pos | Expr |
If | Expr Expr Expr | Expr |
@@ -45,8 +46,6 @@ Int | int | Expr |
Str | string ATermList | Expr |
Str | string | Expr | ObsoleteStr
ContextElem | string Expr | ContextElem |
# Internal to the parser, doesn't occur in ASTs.
IndStr | string | Expr |
@@ -68,27 +67,25 @@ PrimOp | int ATermBlob ATermList | Expr |
Attrs | ATermList | Expr |
Closed | Expr | Expr |
Rec | ATermList ATermList | Expr |
Bool | ATermBool | Expr |
Bool | ATerm | Expr |
Null | | Expr |
Bind | string Expr Pos | ATerm |
BindAttrPath | ATermList Expr Pos | ATerm | # desugared during parsing
Bind | string Expr | ATerm | ObsoleteBind
Inherit | Expr ATermList Pos | ATerm |
Scope | | Expr |
VarPat | string | Pattern |
AttrsPat | ATermList ATermBool | Pattern | # bool = `...'
AtPat | Pattern Pattern | Pattern |
Formal | string ValidValues DefaultValue | ATerm |
Formal | string DefaultValue | ATerm |
ValidValues | ATermList | ValidValues |
UnrestrictedValues | | ValidValues |
DefaultValue | Expr | DefaultValue |
NoDefaultValue | | DefaultValue |
True | | ATermBool |
False | | ATermBool |
True | | ATerm |
False | | ATerm |
PrimOpDef | int ATermBlob | ATerm |
@@ -96,4 +93,3 @@ AttrRHS | Expr Pos | ATerm |
eTrue = makeBool(makeTrue())
eFalse = makeBool(makeFalse())
sOverrides = toATerm("__overrides")

View File

@@ -6,8 +6,6 @@
#include "nixexpr-ast.hh"
#include "nixexpr-ast.cc"
#include <cstdlib>
namespace nix {
@@ -19,7 +17,7 @@ string showPos(ATerm pos)
if (matchNoPos(pos)) return "undefined position";
if (!matchPos(pos, path, line, column))
throw badTerm("position expected", pos);
return (format("`%1%:%2%:%3%'") % aterm2String(path) % line % column).str();
return (format("`%1%', line %2%") % aterm2String(path) % line).str();
}
@@ -110,31 +108,6 @@ Expr makeAttrs(const ATermMap & attrs)
}
static void varsBoundByPattern(ATermMap & map, Pattern pat)
{
ATerm name;
ATermList formals;
Pattern pat1, pat2;
ATermBool ellipsis;
/* Use makeRemoved() so that it can be used directly in
substitute(). */
if (matchVarPat(pat, name))
map.set(name, makeRemoved());
else if (matchAttrsPat(pat, formals, ellipsis)) {
for (ATermIterator i(formals); i; ++i) {
ATerm d1;
if (!matchFormal(*i, name, d1)) abort();
map.set(name, makeRemoved());
}
}
else if (matchAtPat(pat, pat1, pat2)) {
varsBoundByPattern(map, pat1);
varsBoundByPattern(map, pat2);
}
else abort();
}
Expr substitute(const Substitution & subs, Expr e)
{
checkInterrupt();
@@ -160,17 +133,27 @@ Expr substitute(const Substitution & subs, Expr e)
/* In case of a function, filter out all variables bound by this
function. */
Pattern pat;
ATermList formals;
ATerm body;
if (matchFunction(e, pat, body, pos)) {
ATermMap map(16);
varsBoundByPattern(map, pat);
if (matchFunction(e, formals, body, pos)) {
ATermMap map(ATgetLength(formals));
for (ATermIterator i(formals); i; ++i) {
ATerm d1, d2;
if (!matchFormal(*i, name, d1, d2)) abort();
map.set(name, makeRemoved());
}
Substitution subs2(&subs, &map);
return makeFunction(
(Pattern) substitute(subs2, (Expr) pat),
(ATermList) substitute(subs2, (ATerm) formals),
substitute(subs2, body), pos);
}
if (matchFunction1(e, name, body, pos)) {
ATermMap map(1);
map.set(name, makeRemoved());
return makeFunction1(name, substitute(Substitution(&subs, &map), body), pos);
}
/* Idem for a mutually recursive attribute set. */
ATermList rbnds, nrbnds;
if (matchRec(e, rbnds, nrbnds)) {
@@ -228,9 +211,9 @@ static void checkVarDefs2(set<Expr> & done, const ATermMap & defs, Expr e)
done.insert(e);
ATerm name, pos, value;
ATermList formals;
ATerm with, body;
ATermList rbnds, nrbnds;
Pattern pat;
/* Closed terms don't have free variables, so we don't have to
check by definition. */
@@ -242,11 +225,28 @@ static void checkVarDefs2(set<Expr> & done, const ATermMap & defs, Expr e)
% aterm2String(name));
}
else if (matchFunction(e, pat, body, pos)) {
else if (matchFunction(e, formals, body, pos)) {
ATermMap defs2(defs);
varsBoundByPattern(defs2, pat);
for (ATermIterator i(formals); i; ++i) {
ATerm d1, d2;
if (!matchFormal(*i, name, d1, d2)) abort();
defs2.set(name, (ATerm) ATempty);
}
for (ATermIterator i(formals); i; ++i) {
ATerm valids, deflt;
set<Expr> done2;
if (!matchFormal(*i, name, valids, deflt)) abort();
checkVarDefs2(done, defs, valids);
checkVarDefs2(done2, defs2, deflt);
}
set<Expr> done2;
checkVarDefs2(done2, defs2, body);
}
else if (matchFunction1(e, name, body, pos)) {
ATermMap defs2(defs);
defs2.set(name, (ATerm) ATempty);
set<Expr> done2;
checkVarDefs2(done2, defs2, pat);
checkVarDefs2(done2, defs2, body);
}
@@ -336,63 +336,41 @@ Expr makeBool(bool b)
}
bool matchStr(Expr e, string & s, ATermList & context)
bool matchStr(Expr e, string & s, PathSet & context)
{
ATermList l;
ATerm s_;
if (!matchStr(e, s_, context)) return false;
if (!matchStr(e, s_, l)) return false;
s = aterm2String(s_);
for (ATermIterator i(l); i; ++i)
context.insert(aterm2String(*i));
return true;
}
bool matchStr(Expr e, string & s, Context & context)
Expr makeStr(const string & s, const PathSet & context)
{
ATermList c;
if (!matchStr(e, s, c)) return false;
matchContext(c, context);
return true;
}
Expr makeStr(const string & s, ATermList context)
{
return makeStr(toATerm(s), context);
}
Expr makeStr(const string & s, const Context & context)
{
ATermList l = ATempty;
/* !!! should define a canonical ordering of context elements. */
foreach (Context::const_iterator, i, context)
l = ATinsert(l, makeContextElem(i->key, i->value));
return makeStr(s, l);
}
void matchContext(ATermList context, Context & result)
{
for (ATermIterator i(context); i; ++i) {
ATerm s, e;
if (!matchContextElem(*i, s, e)) abort();
result.set(s, e);
}
return makeStr(toATerm(s), toATermList(context));
}
string showType(Expr e)
{
ATerm t1, t2;
ATerm t1, t2, t3;
ATermList l1;
ATermBlob b1;
int i1;
Pattern p1;
if (matchStr(e, t1, l1)) return "a string";
if (matchPath(e, t1)) return "a path";
if (matchNull(e)) return "null";
if (matchInt(e, i1)) return "an integer";
if (matchBool(e, t1)) return "a boolean";
if (matchFunction(e, p1, t1, t2)) return "a function";
if (matchFunction(e, l1, t1, t2)) return "a function";
if (matchFunction1(e, t1, t2, t3)) return "a function";
if (matchAttrs(e, l1)) return "an attribute set";
if (matchList(e, l1)) return "a list";
if (matchPrimOp(e, i1, b1, l1)) return "a partially applied built-in function";
@@ -402,7 +380,7 @@ string showType(Expr e)
string showValue(Expr e)
{
ATermList context;
PathSet context;
string s;
ATerm s2;
int i;

View File

@@ -11,7 +11,6 @@ namespace nix {
MakeError(EvalError, Error)
MakeError(ParseError, Error)
MakeError(AssertionError, EvalError)
MakeError(ThrownError, AssertionError)
MakeError(Abort, EvalError)
@@ -22,11 +21,11 @@ MakeError(TypeError, EvalError)
property of the ATerm library allows us to implement caching of
normals forms efficiently. */
typedef ATerm Expr;
typedef ATerm DefaultValue;
typedef ATerm ValidValues;
typedef ATerm Pos;
typedef ATerm Pattern;
typedef ATerm ATermBool;
typedef ATerm ContextElem;
/* A STL vector of ATerms. Should be used with great care since it's
@@ -105,18 +104,11 @@ Expr canonicaliseExpr(Expr e);
Expr makeBool(bool b);
/* Manipulation of Str() nodes. */
typedef ATermMap Context;
/* Manipulation of Str() nodes. Note: matchStr() does not clear
context! */
bool matchStr(Expr e, string & s, PathSet & context);
bool matchStr(Expr e, string & s, ATermList & context);
bool matchStr(Expr e, string & s, Context & context);
Expr makeStr(const string & s, ATermList context = ATempty);
Expr makeStr(const string & s, const Context & context);
void matchContext(ATermList context, Context & result);
Expr makeStr(const string & s, const PathSet & context = PathSet());
/* Showing types, values. */

View File

@@ -25,7 +25,6 @@
#include "parser-tab.hh"
#include "lexer-tab.hh"
#define YYSTYPE YYSTYPE // workaround a bug in Bison 2.4
#include "nixexpr.hh"
#include "nixexpr-ast.hh"
@@ -44,128 +43,28 @@ struct ParseData
Path path;
string error;
};
static string showAttrPath(ATermList attrPath)
static Expr fixAttrs(int recursive, ATermList as)
{
string s;
for (ATermIterator i(attrPath); i; ++i) {
if (!s.empty()) s += '.';
s += aterm2String(*i);
}
return s;
}
struct Tree
{
Expr leaf; ATerm pos; bool recursive;
typedef std::map<ATerm, Tree> Children;
Children children;
Tree() { leaf = 0; recursive = true; }
};
static ATermList buildAttrs(const Tree & t, ATermList & nonrec)
{
ATermList res = ATempty;
for (Tree::Children::const_reverse_iterator i = t.children.rbegin();
i != t.children.rend(); ++i)
if (!i->second.recursive)
nonrec = ATinsert(nonrec, makeBind(i->first, i->second.leaf, i->second.pos));
else
res = ATinsert(res, i->second.leaf
? makeBind(i->first, i->second.leaf, i->second.pos)
: makeBind(i->first, makeAttrs(buildAttrs(i->second, nonrec)), makeNoPos()));
return res;
}
static Expr fixAttrs(bool recursive, ATermList as)
{
Tree attrs;
ATermList bs = ATempty, cs = ATempty;
ATermList * is = recursive ? &cs : &bs;
for (ATermIterator i(as); i; ++i) {
ATermList names, attrPath; Expr src, e; ATerm name, pos;
ATermList names;
Expr src;
ATerm pos;
if (matchInherit(*i, src, names, pos)) {
bool fromScope = matchScope(src);
for (ATermIterator j(names); j; ++j) {
if (attrs.children.find(*j) != attrs.children.end())
throw ParseError(format("duplicate definition of attribute `%1%' at %2%")
% showAttrPath(ATmakeList1(*j)) % showPos(pos));
Tree & t(attrs.children[*j]);
t.leaf = fromScope ? makeVar(*j) : makeSelect(src, *j);
t.pos = pos;
if (recursive && fromScope) t.recursive = false;
Expr rhs = fromScope ? makeVar(*j) : makeSelect(src, *j);
*is = ATinsert(*is, makeBind(*j, rhs, pos));
}
}
else if (matchBindAttrPath(*i, attrPath, e, pos)) {
Tree * t(&attrs);
for (ATermIterator j(attrPath); j; ) {
name = *j; ++j;
if (t->leaf) throw ParseError(format("attribute set containing `%1%' at %2% already defined at %3%")
% showAttrPath(attrPath) % showPos(pos) % showPos (t->pos));
t = &(t->children[name]);
}
if (t->leaf)
throw ParseError(format("duplicate definition of attribute `%1%' at %2% and %3%")
% showAttrPath(attrPath) % showPos(pos) % showPos (t->pos));
if (!t->children.empty())
throw ParseError(format("duplicate definition of attribute `%1%' at %2%")
% showAttrPath(attrPath) % showPos(pos));
t->leaf = e; t->pos = pos;
}
else abort(); /* can't happen */
} else bs = ATinsert(bs, *i);
}
ATermList nonrec = ATempty;
ATermList rec = buildAttrs(attrs, nonrec);
return recursive ? makeRec(rec, nonrec) : makeAttrs(rec);
}
static void checkPatternVars(ATerm pos, ATermMap & map, Pattern pat)
{
ATerm name;
ATermList formals;
Pattern pat1, pat2;
ATermBool ellipsis;
if (matchVarPat(pat, name)) {
if (map.get(name))
throw ParseError(format("duplicate formal function argument `%1%' at %2%")
% aterm2String(name) % showPos(pos));
map.set(name, name);
}
else if (matchAttrsPat(pat, formals, ellipsis)) {
for (ATermIterator i(formals); i; ++i) {
ATerm d1;
if (!matchFormal(*i, name, d1)) abort();
if (map.get(name))
throw ParseError(format("duplicate formal function argument `%1%' at %2%")
% aterm2String(name) % showPos(pos));
map.set(name, name);
}
}
else if (matchAtPat(pat, pat1, pat2)) {
checkPatternVars(pos, map, pat1);
checkPatternVars(pos, map, pat2);
}
else abort();
}
static void checkPatternVars(ATerm pos, Pattern pat)
{
ATermMap map;
checkPatternVars(pos, map, pat);
if (recursive)
return makeRec(bs, cs);
else
return makeAttrs(bs);
}
@@ -247,7 +146,7 @@ static Expr stripIndentation(ATermList es)
/* Remove the last line if it is empty and consists only of
spaces. */
if (n == 1) {
string::size_type p = s2.find_last_of('\n');
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);
}
@@ -309,22 +208,15 @@ static void freeAndUnprotect(void * p)
%union {
ATerm t;
ATermList ts;
struct {
ATermList formals;
bool ellipsis;
} formals;
}
%type <t> start expr expr_function expr_if expr_op
%type <t> expr_app expr_select expr_simple bind inheritsrc formal
%type <t> pattern pattern2
%type <ts> binds ids attrpath expr_list string_parts ind_string_parts
%type <formals> formals
%type <ts> binds ids expr_list formals string_parts ind_string_parts
%token <t> 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
%token ELLIPSIS
%nonassoc IMPL
%left OR
@@ -344,14 +236,16 @@ start: expr { data->result = $1; };
expr: expr_function;
expr_function
: pattern ':' expr_function
{ checkPatternVars(CUR_POS, $1); $$ = makeFunction($1, $3, CUR_POS); }
: '{' formals '}' ':' expr_function
{ $$ = makeFunction($2, $5, CUR_POS); }
| ID ':' expr_function
{ $$ = makeFunction1($1, $3, CUR_POS); }
| ASSERT expr ';' expr_function
{ $$ = makeAssert($2, $4, CUR_POS); }
| WITH expr ';' expr_function
{ $$ = makeWith($2, $4, CUR_POS); }
| LET binds IN expr_function
{ $$ = makeSelect(fixAttrs(true, ATinsert($2, makeBindAttrPath(ATmakeList1(toATerm("<let-body>")), $4, CUR_POS))), toATerm("<let-body>")); }
{ $$ = makeSelect(fixAttrs(1, ATinsert($2, makeBind(toATerm("<let-body>"), $4, CUR_POS))), toATerm("<let-body>")); }
| expr_if
;
@@ -406,12 +300,12 @@ expr_simple
/* Let expressions `let {..., body = ...}' are just desugared
into `(rec {..., body = ...}).body'. */
| LET '{' binds '}'
{ $$ = makeSelect(fixAttrs(true, $3), toATerm("body")); }
{ $$ = makeSelect(fixAttrs(1, $3), toATerm("body")); }
| REC '{' binds '}'
{ $$ = fixAttrs(true, $3); }
{ $$ = fixAttrs(1, $3); }
| '{' binds '}'
{ $$ = fixAttrs(false, $2); }
| '[' expr_list ']' { $$ = makeList(ATreverse($2)); }
{ $$ = fixAttrs(0, $2); }
| '[' expr_list ']' { $$ = makeList($2); }
;
string_parts
@@ -426,24 +320,14 @@ ind_string_parts
| { $$ = ATempty; }
;
pattern
: pattern2 '@' pattern { $$ = makeAtPat($1, $3); }
| pattern2
;
pattern2
: ID { $$ = makeVarPat($1); }
| '{' formals '}' { $$ = makeAttrsPat($2.formals, $2.ellipsis ? eTrue : eFalse); }
;
binds
: binds bind { $$ = ATinsert($1, $2); }
| { $$ = ATempty; }
;
bind
: attrpath '=' expr ';'
{ $$ = makeBindAttrPath(ATreverse($1), $3, CUR_POS); }
: ID '=' expr ';'
{ $$ = makeBind($1, $3, CUR_POS); }
| INHERIT inheritsrc ids ';'
{ $$ = makeInherit($2, $3, CUR_POS); }
;
@@ -455,30 +339,24 @@ inheritsrc
ids: ids ID { $$ = ATinsert($1, $2); } | { $$ = ATempty; };
attrpath
: attrpath '.' ID { $$ = ATinsert($1, $3); }
| ID { $$ = ATmakeList1($1); }
;
expr_list
: expr_list expr_select { $$ = ATinsert($1, $2); }
: expr_select expr_list { $$ = ATinsert($2, $1); }
/* yes, this is right-recursive, but it doesn't matter since
otherwise we would need ATreverse which requires unbounded
stack space */
| { $$ = ATempty; }
;
formals
: formal ',' formals /* !!! right recursive */
{ $$.formals = ATinsert($3.formals, $1); $$.ellipsis = $3.ellipsis; }
| formal
{ $$.formals = ATinsert(ATempty, $1); $$.ellipsis = false; }
|
{ $$.formals = ATempty; $$.ellipsis = false; }
| ELLIPSIS
{ $$.formals = ATempty; $$.ellipsis = true; }
: formal ',' formals { $$ = ATinsert($3, $1); } /* idem - right recursive */
| formal { $$ = ATinsert(ATempty, $1); }
| { $$ = ATempty; }
;
formal
: ID { $$ = makeFormal($1, makeNoDefaultValue()); }
| ID '?' expr { $$ = makeFormal($1, makeDefaultValue($3)); }
: ID { $$ = makeFormal($1, makeUnrestrictedValues(), makeNoDefaultValue()); }
| ID ':' '[' expr_list ']' { $$ = makeFormal($1, makeValidValues($4), makeNoDefaultValue()); }
| ID '?' expr { $$ = makeFormal($1, makeUnrestrictedValues(), makeDefaultValue($3)); }
;
%%
@@ -495,6 +373,63 @@ formal
namespace nix {
static void checkAttrs(ATermMap & names, ATermList bnds)
{
for (ATermIterator i(bnds); i; ++i) {
ATerm name;
Expr e;
ATerm pos;
if (!matchBind(*i, name, e, pos)) abort(); /* can't happen */
if (names.get(name))
throw EvalError(format("duplicate attribute `%1%' at %2%")
% aterm2String(name) % showPos(pos));
names.set(name, name);
}
}
static void checkAttrSets(ATerm e)
{
ATermList formals;
ATerm body, pos;
if (matchFunction(e, formals, body, pos)) {
ATermMap names(ATgetLength(formals));
for (ATermIterator i(formals); i; ++i) {
ATerm name;
ATerm d1, d2;
if (!matchFormal(*i, name, d1, d2)) abort();
if (names.get(name))
throw EvalError(format("duplicate formal function argument `%1%' at %2%")
% aterm2String(name) % showPos(pos));
names.set(name, name);
}
}
ATermList bnds;
if (matchAttrs(e, bnds)) {
ATermMap names(ATgetLength(bnds));
checkAttrs(names, bnds);
}
ATermList rbnds, nrbnds;
if (matchRec(e, rbnds, nrbnds)) {
ATermMap names(ATgetLength(rbnds) + ATgetLength(nrbnds));
checkAttrs(names, rbnds);
checkAttrs(names, nrbnds);
}
if (ATgetType(e) == AT_APPL) {
int arity = ATgetArity(ATgetAFun(e));
for (int i = 0; i < arity; ++i)
checkAttrSets(ATgetArgument(e, i));
}
else if (ATgetType(e) == AT_LIST)
for (ATermIterator i((ATermList) e); i; ++i)
checkAttrSets(*i);
}
static Expr parse(EvalState & state,
const char * text, const Path & path,
const Path & basePath)
@@ -509,14 +444,16 @@ static Expr parse(EvalState & state,
int res = yyparse(scanner, &data);
yylex_destroy(scanner);
if (res) throw ParseError(data.error);
if (res) throw EvalError(data.error);
try {
checkVarDefs(state.primOps, data.result);
} catch (Error & e) {
throw ParseError(format("%1%, in `%2%'") % e.msg() % path);
throw EvalError(format("%1%, in `%2%'") % e.msg() % path);
}
checkAttrSets(data.result);
return data.result;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
pkglib_LTLIBRARIES = libext3cow.la
libext3cow_la_SOURCES = epoch2date.c snapshot.cc tt.c ext3cow_tools.h ext3cow_fs.h
pkginclude_HEADERS = snapshot.hh
#TODO linux kernel header
libext3cow_la_LIBADD = ../libutil/libutil.la \
../boost/format/libformat.la
AM_CXXFLAGS = -Wall \
-I$(srcdir)/.. ${aterm_include} \
-I$(srcdir)/../libutil
AM_CFLAGS = \
${aterm_include}

View File

@@ -0,0 +1,24 @@
/* epoch2date.c - an ext3cow tool for turning epoch numbers into dates.
* Copyright (C) 2003-2007 Zachary N. J. Peterson
*/
#include "ext3cow_tools.h"
int main(int argc, char** argv){
time_t time;
if(argc < 2){
fprintf(stderr, "usage: %s seconds\n", argv[0]);
exit(1);
}
time = atoi(argv[1]);
printf("%s", ctime(&time));
return 0;
}

View File

@@ -0,0 +1,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <time.h>
#include <sys/time.h>
#include "ext3cow_fs.h"

View File

@@ -0,0 +1,97 @@
/* snapshot.c - an ext3cow tool for taking file system snapshots
* Copyright (C) 2003-2007 Zachary N. J. Peterson
*/
#include "ext3cow_tools.h"
#include "snapshot.hh"
#include "types.hh"
//using namespace nix;
namespace nix {
/////////////////////Original functions commented out:
/*
void snapshot_usage(void){
fprintf(stderr, "usage: snapshot <mountpoint>\n");
}
int snapshot_main(int argc, char** argv){
int fd;
int ret;
unsigned int epoch = 0;
char path[256] = ".\0";
if(argc > 1)
strcpy(path, argv[1]);
printf("Snapshot on %s: ", path);
fd = open(path, O_RDONLY);
// test for ext3cow fs type
if(fd < 0){
printf("failed.\n");
perror(argv[0]);
exit(1);
}
epoch = (int)ioctl(fd, EXT3COW_IOC_TAKESNAPSHOT, &epoch);
if((int)epoch < 0){
printf("failed.\n");
perror(argv[0]);
exit(1);
}
printf("%u\n", (unsigned int)epoch);
return 0;
}
*/
/////////////////////End original functions
unsigned int take_snapshot(const string & dir2) //const string & file_or_dir)
{
const char* dir = dir2.c_str();
int fd;
unsigned int epoch = 0;
//char path[256] = ".\0";
//TODO 256 length check ???
//strcpy(path, dir);
fd = open(dir, O_RDONLY);
/* test for ext3cow fs type */
if(fd < 0){
printf("failed.\n");
perror(dir);
exit(1);
}
epoch = (int)ioctl(fd, EXT3COW_IOC_TAKESNAPSHOT, &epoch);
if((int)epoch < 0){
printf("failed.\n");
perror(dir);
exit(1);
}
//printf("%u\n", (unsigned int)epoch);
return epoch;
}
}

View File

@@ -0,0 +1,13 @@
#ifndef SNAPSHOT_H_
#define SNAPSHOT_H_
#include "types.hh"
namespace nix {
//unsigned int take_snapshot(const string & file_or_dir);
unsigned int take_snapshot(const string & dir);
}
#endif /*SNAPSHOT_H_*/

46
src/libext3cow/tt.c Normal file
View File

@@ -0,0 +1,46 @@
/* tt.c - an ext3cow tool for retreiving the current file system epoch
* Copyright (C) 2003-2007 Zachary N. J. Peterson
*/
#include "ext3cow_tools.h"
void tt_usage(void){
fprintf(stderr, "usage: tt <mountpoint>\n");
}
int tt_main(int argc, char** argv){
int fd;
int ret;
unsigned int epoch = 0;
char path[255] = ".\0";
if(argc > 1)
strcpy(path, argv[1]);
fd = open(path, O_RDONLY);
/* test for ext3cow fs type */
if(fd < 0){
fprintf(stderr, "Couldn't open %s\n", path);
exit(1);
}
ret = ioctl(fd, EXT3COW_IOC_GETEPOCH, &epoch);
if(ret < 0){
printf("tt on %s failed.\n", path);
perror(argv[0]);
exit(1);
}
printf("Epoch: %d\n", ret);
close(fd);
return 0;
}

View File

@@ -1,13 +1,12 @@
pkglib_LTLIBRARIES = libmain.la
libmain_la_SOURCES = shared.cc
libmain_la_LIBADD = ../libstore/libstore.la
pkginclude_HEADERS = shared.hh
libmain_la_SOURCES = shared.cc shared.hh
AM_CXXFLAGS = \
-DNIX_STORE_DIR=\"$(storedir)\" \
-DNIX_STORE_STATE_DIR=\"$(storestatedir)\" \
-DNIX_EXT3_COW_HEADER=\"$(ext3cowheader)\" \
-DNIX_RSYNC=\"$(rsync)\" \
-DNIX_DATA_DIR=\"$(datadir)\" \
-DNIX_STATE_DIR=\"$(localstatedir)/nix\" \
-DNIX_LOG_DIR=\"$(localstatedir)/log/nix\" \

View File

@@ -4,7 +4,6 @@
#include "globals.hh"
#include "store-api.hh"
#include "util.hh"
#include "misc.hh"
#include <iostream>
#include <cctype>
@@ -50,34 +49,6 @@ void printGCWarning()
}
void printMissing(const PathSet & paths)
{
unsigned long long downloadSize;
PathSet willBuild, willSubstitute, unknown;
queryMissing(paths, willBuild, willSubstitute, unknown, downloadSize);
if (!willBuild.empty()) {
printMsg(lvlInfo, format("the following derivations will be built:"));
foreach (PathSet::iterator, i, willBuild)
printMsg(lvlInfo, format(" %1%") % *i);
}
if (!willSubstitute.empty()) {
printMsg(lvlInfo, format("the following paths will be downloaded/copied (%.2f MiB):") %
(downloadSize / (1024.0 * 1024.0)));
foreach (PathSet::iterator, i, willSubstitute)
printMsg(lvlInfo, format(" %1%") % *i);
}
if (!unknown.empty()) {
printMsg(lvlInfo, format("don't know how to build the following paths%1%:")
% (readOnlyMode ? " (may be caused by read-only store access)" : ""));
foreach (PathSet::iterator, i, unknown)
printMsg(lvlInfo, format(" %1%") % *i);
}
}
static void setLogType(string lt)
{
if (lt == "pretty") logType = ltPretty;
@@ -87,6 +58,27 @@ static void setLogType(string lt)
}
static unsigned int getIntArg(const string & opt,
Strings::iterator & i, const Strings::iterator & end)
{
++i;
if (i == end) throw UsageError(format("`%1%' requires an argument") % opt);
int n;
if (!string2Int(*i, n) || n < 0)
throw UsageError(format("`%1%' requires a non-negative integer") % opt);
return n;
}
struct RemoveTempRoots
{
~RemoveTempRoots()
{
removeTempRoots();
}
};
void initDerivationsHelpers();
@@ -107,34 +99,27 @@ static void closeStore()
}
RemoveTempRoots::~RemoveTempRoots()
{
removeTempRoots();
}
static bool showTrace = false;
/* Initialize and reorder arguments, then call the actual argument
processor. */
static void initAndRun(int argc, char * * argv)
{
/* Setup Nix paths. */
nixStore = canonPath(getEnv("NIX_STORE_DIR", getEnv("NIX_STORE", NIX_STORE_DIR)));
nixStoreState = canonPath(getEnv("NIX_STORE_STATE_DIR", NIX_STORE_STATE_DIR)); //store state dir usually /nix/state
nixDataDir = canonPath(getEnv("NIX_DATA_DIR", NIX_DATA_DIR));
nixLogDir = canonPath(getEnv("NIX_LOG_DIR", NIX_LOG_DIR));
nixStateDir = canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR));
nixStateDir = canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR)); //nix global state dir
nixDBPath = getEnv("NIX_DB_DIR", nixStateDir + "/db");
nixExt3CowHeader = getEnv("NIX_EXT3_COW_HEADER", NIX_EXT3_COW_HEADER);
nixRsync = getEnv("NIX_RSYNC", NIX_RSYNC);
nixConfDir = canonPath(getEnv("NIX_CONF_DIR", NIX_CONF_DIR));
nixLibexecDir = canonPath(getEnv("NIX_LIBEXEC_DIR", NIX_LIBEXEC_DIR));
nixBinDir = canonPath(getEnv("NIX_BIN_DIR", NIX_BIN_DIR));
string subs = getEnv("NIX_SUBSTITUTERS", "default");
if (subs == "default") {
substituters.push_back(nixLibexecDir + "/nix/substituters/copy-from-other-stores.pl");
substituters.push_back(nixLibexecDir + "/nix/substituters/download-using-manifests.pl");
} else
if (subs == "default")
substituters.push_back(nixLibexecDir + "/nix/download-using-manifests.pl");
else
substituters = tokenizeString(subs, ":");
/* Get some settings from the configuration file. */
@@ -143,29 +128,23 @@ static void initAndRun(int argc, char * * argv)
maxSilentTime = queryIntSetting("build-max-silent-time", 0);
/* Catch SIGINT. */
struct sigaction act;
struct sigaction act, oact;
act.sa_handler = sigintHandler;
sigfillset(&act.sa_mask);
act.sa_flags = 0;
if (sigaction(SIGINT, &act, 0))
if (sigaction(SIGINT, &act, &oact))
throw SysError("installing handler for SIGINT");
if (sigaction(SIGTERM, &act, 0))
if (sigaction(SIGTERM, &act, &oact))
throw SysError("installing handler for SIGTERM");
if (sigaction(SIGHUP, &act, 0))
if (sigaction(SIGHUP, &act, &oact))
throw SysError("installing handler for SIGHUP");
/* Ignore SIGPIPE. */
act.sa_handler = SIG_IGN;
act.sa_flags = 0;
if (sigaction(SIGPIPE, &act, 0))
if (sigaction(SIGPIPE, &act, &oact))
throw SysError("ignoring SIGPIPE");
/* Reset SIGCHLD to its default. */
act.sa_handler = SIG_DFL;
act.sa_flags = 0;
if (sigaction(SIGCHLD, &act, 0))
throw SysError("resetting SIGCHLD");
/* There is no privacy in the Nix system ;-) At least not for
now. In particular, store objects should be readable by
everybody. This prevents nasty surprises when using a shared
@@ -184,23 +163,29 @@ static void initAndRun(int argc, char * * argv)
while (argc--) args.push_back(*argv++);
args.erase(args.begin());
/* Expand compound dash options (i.e., `-qlf' -> `-q -l -f'), and
ignore options for the ATerm library. */
for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
string arg = *i;
if (string(arg, 0, 4) == "-at-") ;
else if (arg.length() > 2 && arg[0] == '-' && arg[1] != '-' && !isdigit(arg[1])) {
for (unsigned int j = 1; j < arg.length(); j++)
if (isalpha(arg[j]))
remaining.push_back((string) "-" + arg[j]);
else {
remaining.push_back(string(arg, j));
break;
}
} else remaining.push_back(arg);
/* We dont expand for nix-state since we need to pass arguments to other
* programs that can decide for themselves if they want expansion or not
*/
if(programId != "nix-state")
{
/* Expand compound dash options (i.e., `-qlf' -> `-q -l -f'), and
ignore options for the ATerm library. */
for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
string arg = *i;
if (string(arg, 0, 4) == "-at-") ;
else if (arg.length() > 2 && arg[0] == '-' && arg[1] != '-') {
for (unsigned int j = 1; j < arg.length(); j++)
if (isalpha(arg[j]))
remaining.push_back((string) "-" + arg[j]);
else {
remaining.push_back(string(arg, j));
break;
}
} else remaining.push_back(arg);
}
args = remaining;
remaining.clear();
}
args = remaining;
remaining.clear();
/* Process default options. */
for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
@@ -216,15 +201,15 @@ static void initAndRun(int argc, char * * argv)
; /* !!! obsolete - remove eventually */
else if (arg == "--no-build-output" || arg == "-Q")
buildVerbosity = lvlVomit;
else if (arg == "--print-build-trace")
printBuildTrace = true;
else if (arg == "--help") {
//we need to push back since arguments need to be passed on in the state wrapper script
else if (arg == "--help" && programId != "nix-state") {
printHelp();
return;
remaining.push_back(arg);
}
else if (arg == "--version") {
std::cout << format("%1% (Nix) %2%") % programId % NIX_VERSION << std::endl;
return;
remaining.push_back(arg);
}
else if (arg == "--keep-failed" || arg == "-K")
keepFailed = true;
@@ -233,28 +218,19 @@ static void initAndRun(int argc, char * * argv)
else if (arg == "--fallback")
tryFallback = true;
else if (arg == "--max-jobs" || arg == "-j")
maxBuildJobs = getIntArg<unsigned int>(arg, i, args.end());
maxBuildJobs = getIntArg(arg, i, args.end());
else if (arg == "--readonly-mode")
readOnlyMode = true;
else if (arg == "--max-silent-time")
maxSilentTime = getIntArg<unsigned int>(arg, i, args.end());
maxSilentTime = getIntArg(arg, i, args.end());
else if (arg == "--no-build-hook")
useBuildHook = false;
else if (arg == "--show-trace")
showTrace = true;
else if (arg == "--option") {
++i; if (i == args.end()) throw UsageError("`--option' requires two arguments");
string name = *i;
++i; if (i == args.end()) throw UsageError("`--option' requires two arguments");
string value = *i;
overrideSetting(name, tokenizeString(value));
}
else remaining.push_back(arg);
}
/* Automatically clean up the temporary roots file when we
exit. */
RemoveTempRoots removeTempRoots __attribute__((unused));
RemoveTempRoots removeTempRoots; /* unused variable - don't remove */
/* Make sure that the database gets closed properly, even if
terminate() is called (which happens sometimes due to bugs in
@@ -364,9 +340,7 @@ int main(int argc, char * * argv)
% e.what() % programId);
return 1;
} catch (BaseError & e) {
printMsg(lvlError, format("error: %1%%2%") % (showTrace ? e.prefix() : "") % e.msg());
if (e.prefix() != "" && !showTrace)
printMsg(lvlError, "(use `--show-trace' to show detailed location information)");
printMsg(lvlError, format("error: %1%") % e.msg());
return 1;
} catch (std::exception & e) {
printMsg(lvlError, format("error: %1%") % e.what());

View File

@@ -22,34 +22,16 @@ extern std::string programId;
namespace nix {
MakeError(UsageError, nix::Error);
/* Ugh. No better place to put this. */
Path makeRootName(const Path & gcRoot, int & counter);
void printGCWarning();
void printMissing(const PathSet & paths);
template<class N> N getIntArg(const string & opt,
Strings::iterator & i, const Strings::iterator & end)
{
++i;
if (i == end) throw UsageError(format("`%1%' requires an argument") % opt);
N n;
if (!string2Int(*i, n))
throw UsageError(format("`%1%' requires an integer argument") % opt);
return n;
}
/* Whether we're running setuid. */
extern bool setuidMode;
extern volatile ::sig_atomic_t blockInt;
struct RemoveTempRoots
{
~RemoveTempRoots();
};
MakeError(UsageError, nix::Error);
}

View File

@@ -1,23 +1,24 @@
pkglib_LTLIBRARIES = libstore.la
libstore_la_SOURCES = \
store-api.cc local-store.cc remote-store.cc derivations.cc build.cc misc.cc \
globals.cc references.cc pathlocks.cc gc.cc \
optimise-store.cc
store-api.cc local-store.cc remote-store.cc derivations.cc build.cc misc.cc \
globals.cc db.cc references.cc pathlocks.cc gc.cc store-state.cc
pkginclude_HEADERS = \
store-api.hh local-store.hh remote-store.hh derivations.hh misc.hh \
globals.hh references.hh pathlocks.hh \
worker-protocol.hh
store-api.hh local-store.hh remote-store.hh derivations.hh misc.hh \
globals.hh db.hh references.hh pathlocks.hh \
worker-protocol.hh store-state.hh build.hh
libstore_la_LIBADD = ../libutil/libutil.la ../boost/format/libformat.la @ADDITIONAL_NETWORK_LIBS@
libstore_la_LIBADD = ../libutil/libutil.la \
../libext3cow/libext3cow.la \
../boost/format/libformat.la
BUILT_SOURCES = derivations-ast.cc derivations-ast.hh
EXTRA_DIST = derivations-ast.def derivations-ast.cc
AM_CXXFLAGS = -Wall \
-I$(srcdir)/.. ${aterm_include} -I$(srcdir)/../libutil
-I$(srcdir)/.. ${bdb_include} ${aterm_include} -I$(srcdir)/../libutil -I$(srcdir)/../nix-state -I$(srcdir)/../libext3cow
derivations-ast.cc derivations-ast.hh: ../aterm-helper.pl derivations-ast.def
$(perl) $(srcdir)/../aterm-helper.pl derivations-ast.hh derivations-ast.cc < $(srcdir)/derivations-ast.def

File diff suppressed because it is too large Load Diff

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