* Improvements to profiles. Generations are now per-profile, e.g.,
default -> default-94-link default-82-link -> /nix/store/cc4480... default-83-link -> /nix/store/caeec8... ... default-94-link -> /nix/store/2896ca... experimental -> experimental-2-link experimental-1-link -> /nix/store/cc4480... experimental-2-link -> /nix/store/a3148f... * `--profile' / `-p' -> `--switch-profile' / `-S' * `--link' / `-l' -> `--profile' / `-p' * The default profile is stored in $prefix/var/nix/profiles. $prefix/var/nix/links is gone. Profiles can be stored anywhere. * The current profile is now referenced from ~/.nix-profile, not ~/.nix-userenv. * The roots to the garbage collector now have extension `.gcroot', not `.id'.
This commit is contained in:
		
							parent
							
								
									d445da7a7b
								
							
						
					
					
						commit
						66e94d3275
					
				
					 10 changed files with 84 additions and 78 deletions
				
			
		|  | @ -192,9 +192,9 @@ rm -rf /nix/var</screen> | |||
|       To use Nix, some environment variables should be set.  In | ||||
|       particular, <envar>PATH</envar> should contain the directories | ||||
|       <filename><replaceable>prefix</replaceable>/bin</filename> and | ||||
|       <filename>~/.nix-userenv/bin</filename>.  The first directory | ||||
|       <filename>~/.nix-profile/bin</filename>.  The first directory | ||||
|       contains the Nix tools themselves, while | ||||
|       <filename>~/.nix-userenv</filename> is a symbolic link to the | ||||
|       <filename>~/.nix-profile</filename> is a symbolic link to the | ||||
|       current <emphasis>user environment</emphasis> (an automatically | ||||
|       generated package consisting of symlinks to installed packages). | ||||
|       The simplest way to set the required environment variables is to | ||||
|  |  | |||
|  | @ -111,14 +111,14 @@ | |||
|       </varlistentry> | ||||
| 
 | ||||
|       <varlistentry> | ||||
|         <term><filename>~/.nix-userenv</filename></term> | ||||
|         <term><filename>~/.nix-profile</filename></term> | ||||
|         <listitem> | ||||
|           <para> | ||||
|             A symbolic link to the user's current user environment. | ||||
|             By default, it points to | ||||
|             <filename><replaceable>prefix</replaceable>/var/nix/links/current</filename>. | ||||
|             A symbolic link to the user's current profile.  The | ||||
|             default profile is | ||||
|             <filename><replaceable>prefix</replaceable>/var/nix/profiles/default</filename>. | ||||
|             The <envar>PATH</envar> environment variable should | ||||
|             include <filename>~/.nix-userenv</filename> for the user | ||||
|             include <filename>~/.nix-profile/bin</filename> for the user | ||||
|             environment to be visible to the user. | ||||
|           </para> | ||||
|         </listitem> | ||||
|  |  | |||
|  | @ -189,30 +189,32 @@ obtaining list of Nix archives at http://catamaran.labs.cs.uu.nl/dist/nix/nixpkg | |||
|       it can be used immediately, that is, it now appears in a directory in the | ||||
|       <envar>PATH</envar> environment variable.  Specifically, | ||||
|       <envar>PATH</envar> includes the entry | ||||
|       <filename><replaceable>prefix</replaceable>/var/nix/links/current/bin</filename>,  | ||||
|       <filename><replaceable>prefix</replaceable>/var/nix/profiles/default/bin</filename>,  | ||||
|       where | ||||
|       <filename><replaceable>prefix</replaceable>/var/nix/links/current</filename>  | ||||
|       <filename><replaceable>prefix</replaceable>/var/nix/profiles/default</filename>  | ||||
|       is just a symlink to the current user environment: | ||||
|     </para> | ||||
| 
 | ||||
|     <screen> | ||||
| $ ls -l /nix/var/nix/links/ | ||||
| $ ls -l /nix/var/nix/profiles/ | ||||
| ... | ||||
| lrwxrwxrwx  1 eelco ... 15 -> /nix/store/1871...12b0-user-environment | ||||
| lrwxrwxrwx  1 eelco ... 16 -> /nix/store/59ba...df6b-user-environment | ||||
| lrwxrwxrwx  1 eelco ... current -> /nix/var/nix/links/16</screen> | ||||
| lrwxrwxrwx  1 eelco ... default-15-link -> /nix/store/1871...12b0-user-environment | ||||
| lrwxrwxrwx  1 eelco ... default-16-link -> /nix/store/59ba...df6b-user-environment | ||||
| lrwxrwxrwx  1 eelco ... default -> default-16-link</screen> | ||||
| 
 | ||||
|     <para> | ||||
|       That is, <filename>current</filename> in this example is a link to | ||||
|       <filename>16</filename>, which is the current user environment.  Before | ||||
|       the installation, it pointed to <filename>15</filename>.  Note that this | ||||
|       means that you can atomically roll-back to the previous user environment | ||||
|       by pointing the symlink <filename>current</filename> at | ||||
|       <filename>15</filename> again.  This also shows that operations such as | ||||
|       installation are atomic in the Nix system: any arbitrarily complex | ||||
|       set of installation, uninstallation, or upgrade actions eventually boil | ||||
|       down to the single operation of pointing a symlink somewhere else (which | ||||
|       can be implemented atomically in Unix). | ||||
|       That is, <filename>default</filename> in this example is a link | ||||
|       to <filename>default-16-link</filename>, which is the current | ||||
|       user environment.  Before the installation, it pointed to | ||||
|       <filename>default-15-link</filename>.  Note that this means that | ||||
|       you can atomically roll-back to the previous user environment by | ||||
|       pointing the symlink <filename>default</filename> at | ||||
|       <filename>default-15-link</filename> again.  This also shows | ||||
|       that operations such as installation are atomic in the Nix | ||||
|       system: any arbitrarily complex set of installation, | ||||
|       uninstallation, or upgrade actions eventually boil down to the | ||||
|       single operation of pointing a symlink somewhere else (which can | ||||
|       be implemented atomically in Unix). | ||||
|     </para> | ||||
| 
 | ||||
|     <para> | ||||
|  | @ -221,15 +223,15 @@ lrwxrwxrwx  1 eelco ... current -> /nix/var/nix/links/16</screen> | |||
|     </para> | ||||
| 
 | ||||
|     <screen> | ||||
| $ ls -l /nix/var/nix/links/16/bin | ||||
| $ ls -l /nix/var/nix/profiles/default-16-link/bin | ||||
| lrwxrwxrwx  1 eelco ... MozillaFirebird -> /nix/store/35f8...4ae6-MozillaFirebird-0.7/bin/MozillaFirebird | ||||
| lrwxrwxrwx  1 eelco ... svn -> /nix/store/3829...fb5d-subversion-0.32.1/bin/svn | ||||
| ...</screen> | ||||
| 
 | ||||
|     <para> | ||||
|       Note that, e.g., <filename>svn</filename> = | ||||
|       <filename>/nix/var/nix/links/current/bin/svn</filename> = | ||||
|       <filename>/nix/var/nix/links/16/bin/svn</filename> = | ||||
|       <filename>/nix/var/nix/profiles/default/bin/svn</filename> = | ||||
|       <filename>/nix/var/nix/profiles/default-16-link/bin/svn</filename> = | ||||
|       <filename>/nix/store/59ba...df6b-user-environment/bin/svn</filename> = | ||||
|       <filename>/nix/store/3829...fb5d-subversion-0.32.1/bin/svn</filename>. | ||||
|     </para> | ||||
|  |  | |||
|  | @ -93,7 +93,7 @@ $ nix-env -iBf nixpkgs-<replaceable>version</replaceable>/ hello MozillaFirebird | |||
| 
 | ||||
|         <screen> | ||||
| $ which hello | ||||
| /home/eelco/.nix-userenv/bin/hello | ||||
| /home/eelco/.nix-profile/bin/hello | ||||
| $ hello | ||||
| Hello, world! | ||||
| $ MozillaFirebird | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| use strict; | ||||
| use IPC::Open2; | ||||
| 
 | ||||
| my $linkdir = "@localstatedir@/nix/links"; | ||||
| my $linkdir = "@localstatedir@/nix/profiles"; | ||||
| my $storedir = "@prefix@/store"; | ||||
| 
 | ||||
| my %alive; | ||||
|  | @ -24,7 +24,7 @@ closedir DIR; | |||
| my @roots; | ||||
| foreach my $link (@links) { | ||||
|     $link = $linkdir . "/" . $link; | ||||
|     next if (!($link =~ /.id$/)); | ||||
|     next if (!($link =~ /.gcroot$/)); | ||||
|     open ROOT, "<$link" or die "cannot open $link: $!"; | ||||
|     my $root = <ROOT>; | ||||
|     chomp $root; | ||||
|  |  | |||
|  | @ -1,9 +1,9 @@ | |||
| if test -n "$HOME"; then | ||||
|     NIX_LINK="$HOME/.nix-userenv" | ||||
|     NIX_LINK="$HOME/.nix-profile" | ||||
| 
 | ||||
|     if ! test -L "$NIX_LINK"; then | ||||
|         echo "creating $NIX_LINK" | ||||
|         _NIX_DEF_LINK=@localstatedir@/nix/links/current | ||||
|         _NIX_DEF_LINK=@localstatedir@/nix/profiles/default | ||||
|         ln -s "$_NIX_DEF_LINK" "$NIX_LINK" | ||||
|     fi | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,3 +14,6 @@ main.o: help.txt.hh | |||
| AM_CXXFLAGS = \ | ||||
|  -I.. -I../../externals/inst/include -I../libutil -I../libstore \ | ||||
|  -I../libexpr -I../libmain | ||||
| 
 | ||||
| install-data-local: | ||||
| 	$(INSTALL) -d $(DESTDIR)$(localstatedir)/nix/profiles | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ Operations: | |||
| The previous operations take a list of derivation names.  The special | ||||
| name `*' may be used to indicate all derivations. | ||||
| 
 | ||||
|   --profile / -p [FILE]: switch to specified user environment | ||||
|   --switch-profile / -S [FILE]: switch to specified profile | ||||
|   --import / -I FILE: set default Nix expression | ||||
| 
 | ||||
|   --version: output version information | ||||
|  | @ -31,7 +31,7 @@ Query sources: | |||
| 
 | ||||
| Options: | ||||
| 
 | ||||
|   --link / -l LINK: use symlink LINK instead of (...)/current | ||||
|   --profile / -p LINK: use specified profile instead of target of ~/.nix-profile | ||||
|   --file / -f FILE: use Nix expression FILE for installation, etc. | ||||
|   --verbose / -v: verbose operation (may be repeated) | ||||
|   --keep-failed / -K: keep temporary directories of failed builds | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ | |||
| 
 | ||||
| struct Globals | ||||
| { | ||||
|     Path linkPath; | ||||
|     Path profile; | ||||
|     Path nixExprPath; | ||||
|     EvalState state; | ||||
| }; | ||||
|  | @ -116,12 +116,6 @@ static Path getHomeDir() | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| static Path getLinksDir() | ||||
| { | ||||
|     return canonPath(nixStateDir + "/links"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static Path getDefNixExprPath() | ||||
| { | ||||
|     return getHomeDir() + "/.nix-defexpr"; | ||||
|  | @ -143,23 +137,30 @@ void queryInstalled(EvalState & state, DrvInfos & drvs, | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| Path createGeneration(Path outPath, Path drvPath) | ||||
| Path createGeneration(Path profile, Path outPath, Path drvPath) | ||||
| { | ||||
|     Path linksDir = getLinksDir(); | ||||
|     Path profileDir = dirOf(profile); | ||||
|     string profileName = baseNameOf(profile); | ||||
|      | ||||
|     unsigned int num = 0; | ||||
|      | ||||
|     Strings names = readDirectory(linksDir); | ||||
|     Strings names = readDirectory(profileDir); | ||||
|     for (Strings::iterator i = names.begin(); i != names.end(); ++i) { | ||||
|         istringstream s(*i); | ||||
|         if (string(*i, 0, profileName.size() + 1) != profileName + "-") continue; | ||||
|         string s = string(*i, profileName.size() + 1); | ||||
|         int p = s.find("-link"); | ||||
|         if (p == string::npos) continue; | ||||
|         istringstream str(string(s, 0, p)); | ||||
|         unsigned int n; | ||||
|         if (s >> n && s.eof() && n >= num) num = n + 1; | ||||
|         if (str >> n && str.eof() && n >= num) num = n + 1; | ||||
|     } | ||||
| 
 | ||||
|     Path generation; | ||||
|     Path generation, gcrootSrc; | ||||
| 
 | ||||
|     while (1) { | ||||
|         generation = (format("%1%/%2%") % linksDir % num).str(); | ||||
|         Path prefix = (format("%1%-%2%") % profile % num).str(); | ||||
|         generation = prefix + "-link"; | ||||
|         gcrootSrc = prefix + "-src.gcroot"; | ||||
|         if (symlink(outPath.c_str(), generation.c_str()) == 0) break; | ||||
|         if (errno != EEXIST) | ||||
|             throw SysError(format("creating symlink `%1%'") % generation); | ||||
|  | @ -167,7 +168,7 @@ Path createGeneration(Path outPath, Path drvPath) | |||
|         num++; | ||||
|     } | ||||
| 
 | ||||
|     writeStringToFile(generation + "-src.id", drvPath); | ||||
|     writeStringToFile(gcrootSrc, drvPath); | ||||
| 
 | ||||
|     return generation; | ||||
| } | ||||
|  | @ -175,6 +176,9 @@ Path createGeneration(Path outPath, Path drvPath) | |||
| 
 | ||||
| void switchLink(Path link, Path target) | ||||
| { | ||||
|     /* Hacky. */ | ||||
|     if (dirOf(target) == dirOf(link)) target = baseNameOf(target); | ||||
|      | ||||
|     Path tmp = canonPath(dirOf(link) + "/.new_" + baseNameOf(link)); | ||||
|     if (symlink(target.c_str(), tmp.c_str()) != 0) | ||||
|         throw SysError(format("creating symlink `%1%'") % tmp); | ||||
|  | @ -190,7 +194,7 @@ void switchLink(Path link, Path target) | |||
| 
 | ||||
| 
 | ||||
| void createUserEnv(EvalState & state, const DrvInfos & drvs, | ||||
|     const Path & linkPath) | ||||
|     const Path & profile) | ||||
| { | ||||
|     /* Get the environment builder expression. */ | ||||
|     Expr envBuilder = parseExprFromFile(state, | ||||
|  | @ -243,9 +247,9 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs, | |||
| 
 | ||||
|     /* Switch the current user environment to the output path. */ | ||||
|     debug(format("switching to new user environment")); | ||||
|     Path generation = createGeneration( | ||||
|     Path generation = createGeneration(profile, | ||||
|         topLevelDrv.outPath, topLevelDrv.drvPath); | ||||
|     switchLink(linkPath, generation); | ||||
|     switchLink(profile, generation); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -380,7 +384,7 @@ static DrvNames drvNamesFromArgs(const Strings & opArgs) | |||
| 
 | ||||
| 
 | ||||
| static void installDerivations(EvalState & state, | ||||
|     Path nePath, DrvNames & selectors, const Path & linkPath) | ||||
|     Path nePath, DrvNames & selectors, const Path & profile) | ||||
| { | ||||
|     debug(format("installing derivations from `%1%'") % nePath); | ||||
| 
 | ||||
|  | @ -415,10 +419,10 @@ static void installDerivations(EvalState & state, | |||
|      | ||||
|     /* Add in the already installed derivations. */ | ||||
|     DrvInfos installedDrvs; | ||||
|     queryInstalled(state, installedDrvs, linkPath); | ||||
|     queryInstalled(state, installedDrvs, profile); | ||||
|     selectedDrvs.insert(installedDrvs.begin(), installedDrvs.end()); | ||||
| 
 | ||||
|     createUserEnv(state, selectedDrvs, linkPath); | ||||
|     createUserEnv(state, selectedDrvs, profile); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -431,12 +435,12 @@ static void opInstall(Globals & globals, | |||
|     DrvNames drvNames = drvNamesFromArgs(opArgs); | ||||
|      | ||||
|     installDerivations(globals.state, globals.nixExprPath, | ||||
|         drvNames, globals.linkPath); | ||||
|         drvNames, globals.profile); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void upgradeDerivations(EvalState & state, | ||||
|     Path nePath, DrvNames & selectors, const Path & linkPath) | ||||
|     Path nePath, DrvNames & selectors, const Path & profile) | ||||
| { | ||||
|     debug(format("upgrading derivations from `%1%'") % nePath); | ||||
| 
 | ||||
|  | @ -447,7 +451,7 @@ static void upgradeDerivations(EvalState & state, | |||
| 
 | ||||
|     /* Load the currently installed derivations. */ | ||||
|     DrvInfos installedDrvs; | ||||
|     queryInstalled(state, installedDrvs, linkPath); | ||||
|     queryInstalled(state, installedDrvs, profile); | ||||
| 
 | ||||
|     /* Fetch all derivations from the input file. */ | ||||
|     DrvInfos availDrvs; | ||||
|  | @ -496,7 +500,7 @@ static void upgradeDerivations(EvalState & state, | |||
|         newDrvs.insert(*bestDrv); | ||||
|     } | ||||
|      | ||||
|     createUserEnv(state, newDrvs, linkPath); | ||||
|     createUserEnv(state, newDrvs, profile); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -510,15 +514,15 @@ static void opUpgrade(Globals & globals, | |||
|     DrvNames drvNames = drvNamesFromArgs(opArgs); | ||||
|      | ||||
|     upgradeDerivations(globals.state, globals.nixExprPath, | ||||
|         drvNames, globals.linkPath); | ||||
|         drvNames, globals.profile); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void uninstallDerivations(EvalState & state, DrvNames & selectors, | ||||
|     Path & linkPath) | ||||
|     Path & profile) | ||||
| { | ||||
|     DrvInfos installedDrvs; | ||||
|     queryInstalled(state, installedDrvs, linkPath); | ||||
|     queryInstalled(state, installedDrvs, profile); | ||||
| 
 | ||||
|     for (DrvInfos::iterator i = installedDrvs.begin(); | ||||
|          i != installedDrvs.end(); ++i) | ||||
|  | @ -533,7 +537,7 @@ static void uninstallDerivations(EvalState & state, DrvNames & selectors, | |||
|             } | ||||
|     } | ||||
| 
 | ||||
|     createUserEnv(state, installedDrvs, linkPath); | ||||
|     createUserEnv(state, installedDrvs, profile); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -545,7 +549,7 @@ static void opUninstall(Globals & globals, | |||
| 
 | ||||
|     DrvNames drvNames = drvNamesFromArgs(opArgs); | ||||
| 
 | ||||
|     uninstallDerivations(globals.state, drvNames, globals.linkPath); | ||||
|     uninstallDerivations(globals.state, drvNames, globals.profile); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -576,7 +580,7 @@ static void opQuery(Globals & globals, | |||
|     switch (source) { | ||||
| 
 | ||||
|         case sInstalled: | ||||
|             queryInstalled(globals.state, drvs, globals.linkPath); | ||||
|             queryInstalled(globals.state, drvs, globals.profile); | ||||
|             break; | ||||
| 
 | ||||
|         case sAvailable: { | ||||
|  | @ -612,7 +616,7 @@ static void opQuery(Globals & globals, | |||
|          | ||||
|         case qStatus: { | ||||
|             DrvInfos installed; | ||||
|             queryInstalled(globals.state, installed, globals.linkPath); | ||||
|             queryInstalled(globals.state, installed, globals.profile); | ||||
| 
 | ||||
|             PathSet installedPaths; /* output paths of installed drvs */ | ||||
|             for (DrvInfos::iterator i = installed.begin(); | ||||
|  | @ -644,11 +648,11 @@ static void opSwitchProfile(Globals & globals, | |||
|     if (opArgs.size() > 1) | ||||
|         throw UsageError(format("`--profile' takes at most one argument")); | ||||
| 
 | ||||
|     Path linkPath =  | ||||
|         absPath(opArgs.size() == 0 ? globals.linkPath : opArgs.front()); | ||||
|     Path linkPathFinal = getHomeDir() + "/.nix-userenv"; | ||||
|     Path profile =  | ||||
|         absPath(opArgs.size() == 0 ? globals.profile : opArgs.front()); | ||||
|     Path profileLink = getHomeDir() + "/.nix-userenv"; | ||||
| 
 | ||||
|     switchLink(linkPathFinal, linkPath); | ||||
|     switchLink(profileLink, profile); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -676,7 +680,7 @@ void run(Strings args) | |||
|     Operation op = 0; | ||||
|      | ||||
|     Globals globals; | ||||
|     globals.linkPath = getLinksDir() + "/current"; | ||||
|     globals.profile = canonPath(nixStateDir + "/profiles/default"); | ||||
|     globals.nixExprPath = getDefNixExprPath(); | ||||
| 
 | ||||
|     for (Strings::iterator i = args.begin(); i != args.end(); ++i) { | ||||
|  | @ -694,11 +698,11 @@ void run(Strings args) | |||
|             op = opQuery; | ||||
|         else if (arg == "--import" || arg == "-I") /* !!! bad name */ | ||||
|             op = opDefaultExpr; | ||||
|         else if (arg == "--link" || arg == "-l") { | ||||
|         else if (arg == "--profile" || arg == "-p") { | ||||
|             ++i; | ||||
|             if (i == args.end()) throw UsageError( | ||||
|                 format("`%1%' requires an argument") % arg); | ||||
|             globals.linkPath = absPath(*i); | ||||
|             globals.profile = absPath(*i); | ||||
|         } | ||||
|         else if (arg == "--file" || arg == "-f") { | ||||
|             ++i; | ||||
|  | @ -706,7 +710,7 @@ void run(Strings args) | |||
|                 format("`%1%' requires an argument") % arg); | ||||
|             globals.nixExprPath = absPath(*i); | ||||
|         } | ||||
|         else if (arg == "--profile" || arg == "-p")  | ||||
|         else if (arg == "--switch-profile" || arg == "-S") | ||||
|             op = opSwitchProfile; | ||||
|         else if (arg[0] == '-') | ||||
|             opFlags.push_back(arg); | ||||
|  |  | |||
|  | @ -15,9 +15,6 @@ AM_CXXFLAGS = \ | |||
| install-data-local: | ||||
| 	$(INSTALL) -d $(DESTDIR)$(localstatedir)/nix | ||||
| 	$(INSTALL) -d $(DESTDIR)$(localstatedir)/nix/db | ||||
| 	$(INSTALL) -d $(DESTDIR)$(localstatedir)/nix/links | ||||
| 	rm -f $(DESTDIR)$(prefix)/current | ||||
| 	ln -sf $(localstatedir)/nix/links/current $(DESTDIR)$(prefix)/current | ||||
| 	$(INSTALL) -d $(DESTDIR)$(localstatedir)/log/nix | ||||
| 	$(INSTALL) -d $(DESTDIR)$(prefix)/store | ||||
| #	$(bindir)/nix-store --init | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue