* 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:
Eelco Dolstra 2004-02-06 10:30:20 +00:00
parent d445da7a7b
commit 66e94d3275
10 changed files with 84 additions and 78 deletions

View file

@ -192,9 +192,9 @@ rm -rf /nix/var</screen>
To use Nix, some environment variables should be set. In To use Nix, some environment variables should be set. In
particular, <envar>PATH</envar> should contain the directories particular, <envar>PATH</envar> should contain the directories
<filename><replaceable>prefix</replaceable>/bin</filename> and <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 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 current <emphasis>user environment</emphasis> (an automatically
generated package consisting of symlinks to installed packages). generated package consisting of symlinks to installed packages).
The simplest way to set the required environment variables is to The simplest way to set the required environment variables is to

View file

@ -111,14 +111,14 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><filename>~/.nix-userenv</filename></term> <term><filename>~/.nix-profile</filename></term>
<listitem> <listitem>
<para> <para>
A symbolic link to the user's current user environment. A symbolic link to the user's current profile. The
By default, it points to default profile is
<filename><replaceable>prefix</replaceable>/var/nix/links/current</filename>. <filename><replaceable>prefix</replaceable>/var/nix/profiles/default</filename>.
The <envar>PATH</envar> environment variable should 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. environment to be visible to the user.
</para> </para>
</listitem> </listitem>

View file

@ -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 it can be used immediately, that is, it now appears in a directory in the
<envar>PATH</envar> environment variable. Specifically, <envar>PATH</envar> environment variable. Specifically,
<envar>PATH</envar> includes the entry <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 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: is just a symlink to the current user environment:
</para> </para>
<screen> <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 ... default-15-link -> /nix/store/1871...12b0-user-environment
lrwxrwxrwx 1 eelco ... 16 -> /nix/store/59ba...df6b-user-environment lrwxrwxrwx 1 eelco ... default-16-link -> /nix/store/59ba...df6b-user-environment
lrwxrwxrwx 1 eelco ... current -> /nix/var/nix/links/16</screen> lrwxrwxrwx 1 eelco ... default -> default-16-link</screen>
<para> <para>
That is, <filename>current</filename> in this example is a link to That is, <filename>default</filename> in this example is a link
<filename>16</filename>, which is the current user environment. Before to <filename>default-16-link</filename>, which is the current
the installation, it pointed to <filename>15</filename>. Note that this user environment. Before the installation, it pointed to
means that you can atomically roll-back to the previous user environment <filename>default-15-link</filename>. Note that this means that
by pointing the symlink <filename>current</filename> at you can atomically roll-back to the previous user environment by
<filename>15</filename> again. This also shows that operations such as pointing the symlink <filename>default</filename> at
installation are atomic in the Nix system: any arbitrarily complex <filename>default-15-link</filename> again. This also shows
set of installation, uninstallation, or upgrade actions eventually boil that operations such as installation are atomic in the Nix
down to the single operation of pointing a symlink somewhere else (which system: any arbitrarily complex set of installation,
can be implemented atomically in Unix). 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>
<para> <para>
@ -221,15 +223,15 @@ lrwxrwxrwx 1 eelco ... current -> /nix/var/nix/links/16</screen>
</para> </para>
<screen> <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 ... MozillaFirebird -> /nix/store/35f8...4ae6-MozillaFirebird-0.7/bin/MozillaFirebird
lrwxrwxrwx 1 eelco ... svn -> /nix/store/3829...fb5d-subversion-0.32.1/bin/svn lrwxrwxrwx 1 eelco ... svn -> /nix/store/3829...fb5d-subversion-0.32.1/bin/svn
...</screen> ...</screen>
<para> <para>
Note that, e.g., <filename>svn</filename> = Note that, e.g., <filename>svn</filename> =
<filename>/nix/var/nix/links/current/bin/svn</filename> = <filename>/nix/var/nix/profiles/default/bin/svn</filename> =
<filename>/nix/var/nix/links/16/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/59ba...df6b-user-environment/bin/svn</filename> =
<filename>/nix/store/3829...fb5d-subversion-0.32.1/bin/svn</filename>. <filename>/nix/store/3829...fb5d-subversion-0.32.1/bin/svn</filename>.
</para> </para>

View file

@ -93,7 +93,7 @@ $ nix-env -iBf nixpkgs-<replaceable>version</replaceable>/ hello MozillaFirebird
<screen> <screen>
$ which hello $ which hello
/home/eelco/.nix-userenv/bin/hello /home/eelco/.nix-profile/bin/hello
$ hello $ hello
Hello, world! Hello, world!
$ MozillaFirebird $ MozillaFirebird

View file

@ -3,7 +3,7 @@
use strict; use strict;
use IPC::Open2; use IPC::Open2;
my $linkdir = "@localstatedir@/nix/links"; my $linkdir = "@localstatedir@/nix/profiles";
my $storedir = "@prefix@/store"; my $storedir = "@prefix@/store";
my %alive; my %alive;
@ -24,7 +24,7 @@ closedir DIR;
my @roots; my @roots;
foreach my $link (@links) { foreach my $link (@links) {
$link = $linkdir . "/" . $link; $link = $linkdir . "/" . $link;
next if (!($link =~ /.id$/)); next if (!($link =~ /.gcroot$/));
open ROOT, "<$link" or die "cannot open $link: $!"; open ROOT, "<$link" or die "cannot open $link: $!";
my $root = <ROOT>; my $root = <ROOT>;
chomp $root; chomp $root;

View file

@ -1,9 +1,9 @@
if test -n "$HOME"; then if test -n "$HOME"; then
NIX_LINK="$HOME/.nix-userenv" NIX_LINK="$HOME/.nix-profile"
if ! test -L "$NIX_LINK"; then if ! test -L "$NIX_LINK"; then
echo "creating $NIX_LINK" 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" ln -s "$_NIX_DEF_LINK" "$NIX_LINK"
fi fi

View file

@ -14,3 +14,6 @@ main.o: help.txt.hh
AM_CXXFLAGS = \ AM_CXXFLAGS = \
-I.. -I../../externals/inst/include -I../libutil -I../libstore \ -I.. -I../../externals/inst/include -I../libutil -I../libstore \
-I../libexpr -I../libmain -I../libexpr -I../libmain
install-data-local:
$(INSTALL) -d $(DESTDIR)$(localstatedir)/nix/profiles

View file

@ -12,7 +12,7 @@ Operations:
The previous operations take a list of derivation names. The special The previous operations take a list of derivation names. The special
name `*' may be used to indicate all derivations. 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 --import / -I FILE: set default Nix expression
--version: output version information --version: output version information
@ -31,7 +31,7 @@ Query sources:
Options: 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. --file / -f FILE: use Nix expression FILE for installation, etc.
--verbose / -v: verbose operation (may be repeated) --verbose / -v: verbose operation (may be repeated)
--keep-failed / -K: keep temporary directories of failed builds --keep-failed / -K: keep temporary directories of failed builds

View file

@ -10,7 +10,7 @@
struct Globals struct Globals
{ {
Path linkPath; Path profile;
Path nixExprPath; Path nixExprPath;
EvalState state; EvalState state;
}; };
@ -116,12 +116,6 @@ static Path getHomeDir()
} }
static Path getLinksDir()
{
return canonPath(nixStateDir + "/links");
}
static Path getDefNixExprPath() static Path getDefNixExprPath()
{ {
return getHomeDir() + "/.nix-defexpr"; 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; unsigned int num = 0;
Strings names = readDirectory(linksDir); Strings names = readDirectory(profileDir);
for (Strings::iterator i = names.begin(); i != names.end(); ++i) { 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; 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) { 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 (symlink(outPath.c_str(), generation.c_str()) == 0) break;
if (errno != EEXIST) if (errno != EEXIST)
throw SysError(format("creating symlink `%1%'") % generation); throw SysError(format("creating symlink `%1%'") % generation);
@ -167,7 +168,7 @@ Path createGeneration(Path outPath, Path drvPath)
num++; num++;
} }
writeStringToFile(generation + "-src.id", drvPath); writeStringToFile(gcrootSrc, drvPath);
return generation; return generation;
} }
@ -175,6 +176,9 @@ Path createGeneration(Path outPath, Path drvPath)
void switchLink(Path link, Path target) void switchLink(Path link, Path target)
{ {
/* Hacky. */
if (dirOf(target) == dirOf(link)) target = baseNameOf(target);
Path tmp = canonPath(dirOf(link) + "/.new_" + baseNameOf(link)); Path tmp = canonPath(dirOf(link) + "/.new_" + baseNameOf(link));
if (symlink(target.c_str(), tmp.c_str()) != 0) if (symlink(target.c_str(), tmp.c_str()) != 0)
throw SysError(format("creating symlink `%1%'") % tmp); throw SysError(format("creating symlink `%1%'") % tmp);
@ -190,7 +194,7 @@ void switchLink(Path link, Path target)
void createUserEnv(EvalState & state, const DrvInfos & drvs, void createUserEnv(EvalState & state, const DrvInfos & drvs,
const Path & linkPath) const Path & profile)
{ {
/* Get the environment builder expression. */ /* Get the environment builder expression. */
Expr envBuilder = parseExprFromFile(state, Expr envBuilder = parseExprFromFile(state,
@ -243,9 +247,9 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs,
/* Switch the current user environment to the output path. */ /* Switch the current user environment to the output path. */
debug(format("switching to new user environment")); debug(format("switching to new user environment"));
Path generation = createGeneration( Path generation = createGeneration(profile,
topLevelDrv.outPath, topLevelDrv.drvPath); 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, 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); debug(format("installing derivations from `%1%'") % nePath);
@ -415,10 +419,10 @@ static void installDerivations(EvalState & state,
/* Add in the already installed derivations. */ /* Add in the already installed derivations. */
DrvInfos installedDrvs; DrvInfos installedDrvs;
queryInstalled(state, installedDrvs, linkPath); queryInstalled(state, installedDrvs, profile);
selectedDrvs.insert(installedDrvs.begin(), installedDrvs.end()); 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); DrvNames drvNames = drvNamesFromArgs(opArgs);
installDerivations(globals.state, globals.nixExprPath, installDerivations(globals.state, globals.nixExprPath,
drvNames, globals.linkPath); drvNames, globals.profile);
} }
static void upgradeDerivations(EvalState & state, 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); debug(format("upgrading derivations from `%1%'") % nePath);
@ -447,7 +451,7 @@ static void upgradeDerivations(EvalState & state,
/* Load the currently installed derivations. */ /* Load the currently installed derivations. */
DrvInfos installedDrvs; DrvInfos installedDrvs;
queryInstalled(state, installedDrvs, linkPath); queryInstalled(state, installedDrvs, profile);
/* Fetch all derivations from the input file. */ /* Fetch all derivations from the input file. */
DrvInfos availDrvs; DrvInfos availDrvs;
@ -496,7 +500,7 @@ static void upgradeDerivations(EvalState & state,
newDrvs.insert(*bestDrv); newDrvs.insert(*bestDrv);
} }
createUserEnv(state, newDrvs, linkPath); createUserEnv(state, newDrvs, profile);
} }
@ -510,15 +514,15 @@ static void opUpgrade(Globals & globals,
DrvNames drvNames = drvNamesFromArgs(opArgs); DrvNames drvNames = drvNamesFromArgs(opArgs);
upgradeDerivations(globals.state, globals.nixExprPath, upgradeDerivations(globals.state, globals.nixExprPath,
drvNames, globals.linkPath); drvNames, globals.profile);
} }
static void uninstallDerivations(EvalState & state, DrvNames & selectors, static void uninstallDerivations(EvalState & state, DrvNames & selectors,
Path & linkPath) Path & profile)
{ {
DrvInfos installedDrvs; DrvInfos installedDrvs;
queryInstalled(state, installedDrvs, linkPath); queryInstalled(state, installedDrvs, profile);
for (DrvInfos::iterator i = installedDrvs.begin(); for (DrvInfos::iterator i = installedDrvs.begin();
i != installedDrvs.end(); ++i) 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); 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) { switch (source) {
case sInstalled: case sInstalled:
queryInstalled(globals.state, drvs, globals.linkPath); queryInstalled(globals.state, drvs, globals.profile);
break; break;
case sAvailable: { case sAvailable: {
@ -612,7 +616,7 @@ static void opQuery(Globals & globals,
case qStatus: { case qStatus: {
DrvInfos installed; DrvInfos installed;
queryInstalled(globals.state, installed, globals.linkPath); queryInstalled(globals.state, installed, globals.profile);
PathSet installedPaths; /* output paths of installed drvs */ PathSet installedPaths; /* output paths of installed drvs */
for (DrvInfos::iterator i = installed.begin(); for (DrvInfos::iterator i = installed.begin();
@ -644,11 +648,11 @@ static void opSwitchProfile(Globals & globals,
if (opArgs.size() > 1) if (opArgs.size() > 1)
throw UsageError(format("`--profile' takes at most one argument")); throw UsageError(format("`--profile' takes at most one argument"));
Path linkPath = Path profile =
absPath(opArgs.size() == 0 ? globals.linkPath : opArgs.front()); absPath(opArgs.size() == 0 ? globals.profile : opArgs.front());
Path linkPathFinal = getHomeDir() + "/.nix-userenv"; Path profileLink = getHomeDir() + "/.nix-userenv";
switchLink(linkPathFinal, linkPath); switchLink(profileLink, profile);
} }
@ -676,7 +680,7 @@ void run(Strings args)
Operation op = 0; Operation op = 0;
Globals globals; Globals globals;
globals.linkPath = getLinksDir() + "/current"; globals.profile = canonPath(nixStateDir + "/profiles/default");
globals.nixExprPath = getDefNixExprPath(); globals.nixExprPath = getDefNixExprPath();
for (Strings::iterator i = args.begin(); i != args.end(); ++i) { for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
@ -694,11 +698,11 @@ void run(Strings args)
op = opQuery; op = opQuery;
else if (arg == "--import" || arg == "-I") /* !!! bad name */ else if (arg == "--import" || arg == "-I") /* !!! bad name */
op = opDefaultExpr; op = opDefaultExpr;
else if (arg == "--link" || arg == "-l") { else if (arg == "--profile" || arg == "-p") {
++i; ++i;
if (i == args.end()) throw UsageError( if (i == args.end()) throw UsageError(
format("`%1%' requires an argument") % arg); format("`%1%' requires an argument") % arg);
globals.linkPath = absPath(*i); globals.profile = absPath(*i);
} }
else if (arg == "--file" || arg == "-f") { else if (arg == "--file" || arg == "-f") {
++i; ++i;
@ -706,7 +710,7 @@ void run(Strings args)
format("`%1%' requires an argument") % arg); format("`%1%' requires an argument") % arg);
globals.nixExprPath = absPath(*i); globals.nixExprPath = absPath(*i);
} }
else if (arg == "--profile" || arg == "-p") else if (arg == "--switch-profile" || arg == "-S")
op = opSwitchProfile; op = opSwitchProfile;
else if (arg[0] == '-') else if (arg[0] == '-')
opFlags.push_back(arg); opFlags.push_back(arg);

View file

@ -15,9 +15,6 @@ AM_CXXFLAGS = \
install-data-local: install-data-local:
$(INSTALL) -d $(DESTDIR)$(localstatedir)/nix $(INSTALL) -d $(DESTDIR)$(localstatedir)/nix
$(INSTALL) -d $(DESTDIR)$(localstatedir)/nix/db $(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)$(localstatedir)/log/nix
$(INSTALL) -d $(DESTDIR)$(prefix)/store $(INSTALL) -d $(DESTDIR)$(prefix)/store
# $(bindir)/nix-store --init # $(bindir)/nix-store --init