* Implemented Eelco V.'s `nix-env -I' command to specify the default
path of the Nix expression to be used with the import, upgrade, and query commands. For instance, $ nix-env -I ~/nixpkgs/pkgs/system/i686-linux.nix $ nix-env --query --available [aka -qa] sylpheed-0.9.7 bison-1.875 pango-1.2.5 subversion-0.35.1 ... $ nix-env -i sylpheed $ nix-env -u subversion There can be only one default at a time. * If the path to a Nix expression is a symlink, follow the symlink prior to resolving relative path references in the expression.
This commit is contained in:
parent
f83c5e3e5f
commit
4a373a3e9a
7 changed files with 87 additions and 43 deletions
|
@ -29,16 +29,12 @@ struct Cleanup : TermFun
|
||||||
ATMatcher m;
|
ATMatcher m;
|
||||||
string s;
|
string s;
|
||||||
|
|
||||||
if (atMatch(m, e) >> "Str" >> s) {
|
if (atMatch(m, e) >> "Str" >> s)
|
||||||
return ATmake("Str(<str>)",
|
return ATmake("Str(<str>)",
|
||||||
string(s, 1, s.size() - 2).c_str());
|
string(s, 1, s.size() - 2).c_str());
|
||||||
}
|
|
||||||
|
|
||||||
if (atMatch(m, e) >> "Path" >> s) {
|
if (atMatch(m, e) >> "Path" >> s)
|
||||||
if (s[0] != '/')
|
return ATmake("Path(<str>)", absPath(s, basePath).c_str());
|
||||||
s = basePath + "/" + s;
|
|
||||||
return ATmake("Path(<str>)", canonPath(s).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (atMatch(m, e) >> "Int" >> s) {
|
if (atMatch(m, e) >> "Int" >> s) {
|
||||||
istringstream s2(s);
|
istringstream s2(s);
|
||||||
|
@ -147,8 +143,14 @@ Expr parseExprFromFile(Path path)
|
||||||
if (e) return e;
|
if (e) return e;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If `path' refers to a directory, append `/default.nix'. */
|
/* If `path' is a symlink, follow it. This is so that relative
|
||||||
|
path references work. */
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
if (lstat(path.c_str(), &st))
|
||||||
|
throw SysError(format("getting status of `%1%'") % path);
|
||||||
|
if (S_ISLNK(st.st_mode)) path = absPath(readLink(path), dirOf(path));
|
||||||
|
|
||||||
|
/* If `path' refers to a directory, append `/default.nix'. */
|
||||||
if (stat(path.c_str(), &st))
|
if (stat(path.c_str(), &st))
|
||||||
throw SysError(format("getting status of `%1%'") % path);
|
throw SysError(format("getting status of `%1%'") % path);
|
||||||
if (S_ISDIR(st.st_mode))
|
if (S_ISDIR(st.st_mode))
|
||||||
|
|
|
@ -59,12 +59,8 @@ void checkPath(const string & path,
|
||||||
delete buf; /* !!! autodelete */
|
delete buf; /* !!! autodelete */
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (S_ISLNK(st.st_mode)) {
|
else if (S_ISLNK(st.st_mode))
|
||||||
char buf[st.st_size];
|
search(readLink(path), ids, seen);
|
||||||
if (readlink(path.c_str(), buf, st.st_size) != st.st_size)
|
|
||||||
throw SysError(format("reading symbolic link `%1%'") % path);
|
|
||||||
search(string(buf, st.st_size), ids, seen);
|
|
||||||
}
|
|
||||||
|
|
||||||
else throw Error(format("unknown file type: %1%") % path);
|
else throw Error(format("unknown file type: %1%") % path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,11 +122,8 @@ static void dump(const Path & path, DumpSink & sink)
|
||||||
else if (S_ISLNK(st.st_mode)) {
|
else if (S_ISLNK(st.st_mode)) {
|
||||||
writeString("type", sink);
|
writeString("type", sink);
|
||||||
writeString("symlink", sink);
|
writeString("symlink", sink);
|
||||||
char buf[st.st_size];
|
|
||||||
if (readlink(path.c_str(), buf, st.st_size) != st.st_size)
|
|
||||||
throw SysError("reading symbolic link " + path);
|
|
||||||
writeString("target", sink);
|
writeString("target", sink);
|
||||||
writeString(string(buf, st.st_size), sink);
|
writeString(readLink(path), sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
else throw Error("unknown file type: " + path);
|
else throw Error("unknown file type: " + path);
|
||||||
|
|
|
@ -109,6 +109,20 @@ bool pathExists(const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Path readLink(const Path & path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if (lstat(path.c_str(), &st))
|
||||||
|
throw SysError(format("getting status of `%1%'") % path);
|
||||||
|
if (!S_ISLNK(st.st_mode))
|
||||||
|
throw Error(format("`%1%' is not a symlink") % path);
|
||||||
|
char buf[st.st_size];
|
||||||
|
if (readlink(path.c_str(), buf, st.st_size) != st.st_size)
|
||||||
|
throw SysError(format("reading symbolic link `%1%'") % path);
|
||||||
|
return string(buf, st.st_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Strings readDirectory(const Path & path)
|
Strings readDirectory(const Path & path)
|
||||||
{
|
{
|
||||||
Strings names;
|
Strings names;
|
||||||
|
|
|
@ -73,6 +73,10 @@ string baseNameOf(const Path & path);
|
||||||
/* Return true iff the given path exists. */
|
/* Return true iff the given path exists. */
|
||||||
bool pathExists(const Path & path);
|
bool pathExists(const Path & path);
|
||||||
|
|
||||||
|
/* Read the contents (target) of a symbolic link. The result is not
|
||||||
|
in any way canonicalised. */
|
||||||
|
Path readLink(const Path & path);
|
||||||
|
|
||||||
/* Read the contents of a directory. The entries `.' and `..' are
|
/* Read the contents of a directory. The entries `.' and `..' are
|
||||||
removed. */
|
removed. */
|
||||||
Strings readDirectory(const Path & path);
|
Strings readDirectory(const Path & path);
|
||||||
|
|
|
@ -4,15 +4,16 @@ nix-env [OPTIONS...] [ARGUMENTS...]
|
||||||
|
|
||||||
Operations:
|
Operations:
|
||||||
|
|
||||||
--install / -i FILE: add derivations to the user environment
|
--install / -i: add derivations to the user environment
|
||||||
|
--upgrade / -u: upgrade derivation in the user environment
|
||||||
--uninstall / -e: remove derivations from the user environment
|
--uninstall / -e: remove derivations from the user environment
|
||||||
--upgrade / -u FILE: upgrade derivation in the user environment
|
|
||||||
--query / -q: perform a query on an environment or Nix expression
|
--query / -q: perform a query on an environment or Nix expression
|
||||||
|
|
||||||
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
|
--profile / -p [FILE]: switch to specified user environment
|
||||||
|
--import / -I FILE: set default Nix expression
|
||||||
|
|
||||||
--version: output version information
|
--version: output version information
|
||||||
--help: display help
|
--help: display help
|
||||||
|
@ -26,10 +27,11 @@ Query types:
|
||||||
Query sources:
|
Query sources:
|
||||||
|
|
||||||
--installed: use installed derivations (default)
|
--installed: use installed derivations (default)
|
||||||
--available / -f FILE: use derivations available in expression FILE
|
--available / -a: use derivations available in Nix expression
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
--link / -l LINK: use symlink LINK instead of (...)/current
|
--link / -l LINK: use symlink LINK instead of (...)/current
|
||||||
|
--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
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
struct Globals
|
struct Globals
|
||||||
{
|
{
|
||||||
Path linkPath;
|
Path linkPath;
|
||||||
|
Path nixExprPath;
|
||||||
EvalState state;
|
EvalState state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,12 +107,26 @@ void loadDerivations(EvalState & state, Path nePath, DrvInfos & drvs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Path getHomeDir()
|
||||||
|
{
|
||||||
|
Path homeDir(getenv("HOME"));
|
||||||
|
if (homeDir == "") throw Error("HOME environment variable not set");
|
||||||
|
return homeDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static Path getLinksDir()
|
static Path getLinksDir()
|
||||||
{
|
{
|
||||||
return canonPath(nixStateDir + "/links");
|
return canonPath(nixStateDir + "/links");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Path getDefNixExprPath()
|
||||||
|
{
|
||||||
|
return getHomeDir() + "/.nix-defexpr";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void queryInstalled(EvalState & state, DrvInfos & drvs,
|
void queryInstalled(EvalState & state, DrvInfos & drvs,
|
||||||
const Path & userEnv)
|
const Path & userEnv)
|
||||||
{
|
{
|
||||||
|
@ -410,13 +425,11 @@ static void opInstall(Globals & globals,
|
||||||
{
|
{
|
||||||
if (opFlags.size() > 0)
|
if (opFlags.size() > 0)
|
||||||
throw UsageError(format("unknown flags `%1%'") % opFlags.front());
|
throw UsageError(format("unknown flags `%1%'") % opFlags.front());
|
||||||
if (opArgs.size() < 1) throw UsageError("Nix file expected");
|
|
||||||
|
|
||||||
Path nePath = opArgs.front();
|
DrvNames drvNames = drvNamesFromArgs(opArgs);
|
||||||
DrvNames drvNames = drvNamesFromArgs(
|
|
||||||
Strings(++opArgs.begin(), opArgs.end()));
|
|
||||||
|
|
||||||
installDerivations(globals.state, nePath, drvNames, globals.linkPath);
|
installDerivations(globals.state, globals.nixExprPath,
|
||||||
|
drvNames, globals.linkPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -492,11 +505,10 @@ static void opUpgrade(Globals & globals,
|
||||||
throw UsageError(format("unknown flags `%1%'") % opFlags.front());
|
throw UsageError(format("unknown flags `%1%'") % opFlags.front());
|
||||||
if (opArgs.size() < 1) throw UsageError("Nix file expected");
|
if (opArgs.size() < 1) throw UsageError("Nix file expected");
|
||||||
|
|
||||||
Path nePath = opArgs.front();
|
DrvNames drvNames = drvNamesFromArgs(opArgs);
|
||||||
DrvNames drvNames = drvNamesFromArgs(
|
|
||||||
Strings(++opArgs.begin(), opArgs.end()));
|
|
||||||
|
|
||||||
upgradeDerivations(globals.state, nePath, drvNames, globals.linkPath);
|
upgradeDerivations(globals.state, globals.nixExprPath,
|
||||||
|
drvNames, globals.linkPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -547,7 +559,7 @@ static void opQuery(Globals & globals,
|
||||||
else if (*i == "--expr" || *i == "-e") query = qDrvPath;
|
else if (*i == "--expr" || *i == "-e") query = qDrvPath;
|
||||||
else if (*i == "--status" || *i == "-s") query = qStatus;
|
else if (*i == "--status" || *i == "-s") query = qStatus;
|
||||||
else if (*i == "--installed") source = sInstalled;
|
else if (*i == "--installed") source = sInstalled;
|
||||||
else if (*i == "--available" || *i == "-f") source = sAvailable;
|
else if (*i == "--available" || *i == "-a") source = sAvailable;
|
||||||
else throw UsageError(format("unknown flag `%1%'") % *i);
|
else throw UsageError(format("unknown flag `%1%'") % *i);
|
||||||
|
|
||||||
/* Obtain derivation information from the specified source. */
|
/* Obtain derivation information from the specified source. */
|
||||||
|
@ -560,10 +572,7 @@ static void opQuery(Globals & globals,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sAvailable: {
|
case sAvailable: {
|
||||||
if (opArgs.size() < 1) throw UsageError("Nix file expected");
|
loadDerivations(globals.state, globals.nixExprPath, drvs);
|
||||||
Path nePath = opArgs.front();
|
|
||||||
opArgs.pop_front();
|
|
||||||
loadDerivations(globals.state, nePath, drvs);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,20 +620,31 @@ static void opSwitchProfile(Globals & globals,
|
||||||
if (opFlags.size() > 0)
|
if (opFlags.size() > 0)
|
||||||
throw UsageError(format("unknown flags `%1%'") % opFlags.front());
|
throw UsageError(format("unknown flags `%1%'") % opFlags.front());
|
||||||
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"));
|
||||||
|
|
||||||
string linkPath =
|
Path linkPath =
|
||||||
opArgs.size() == 0 ? globals.linkPath : opArgs.front();
|
opArgs.size() == 0 ? globals.linkPath : opArgs.front();
|
||||||
|
Path linkPathFinal = getHomeDir() + "/.nix-userenv";
|
||||||
|
|
||||||
string homeDir(getenv("HOME"));
|
|
||||||
if (homeDir == "") throw Error("HOME environment variable not set");
|
|
||||||
|
|
||||||
string linkPathFinal = homeDir + "/.nix-userenv";
|
|
||||||
|
|
||||||
switchLink(linkPathFinal, linkPath);
|
switchLink(linkPathFinal, linkPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void opDefaultExpr(Globals & globals,
|
||||||
|
Strings opFlags, Strings opArgs)
|
||||||
|
{
|
||||||
|
if (opFlags.size() > 0)
|
||||||
|
throw UsageError(format("unknown flags `%1%'") % opFlags.front());
|
||||||
|
if (opArgs.size() != 1)
|
||||||
|
throw UsageError(format("`--import' takes exactly one argument"));
|
||||||
|
|
||||||
|
Path defNixExpr = opArgs.front();
|
||||||
|
Path defNixExprLink = getDefNixExprPath();
|
||||||
|
|
||||||
|
switchLink(defNixExprLink, defNixExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void run(Strings args)
|
void run(Strings args)
|
||||||
{
|
{
|
||||||
/* Use a higher default verbosity (lvlInfo). */
|
/* Use a higher default verbosity (lvlInfo). */
|
||||||
|
@ -635,6 +655,7 @@ void run(Strings args)
|
||||||
|
|
||||||
Globals globals;
|
Globals globals;
|
||||||
globals.linkPath = getLinksDir() + "/current";
|
globals.linkPath = getLinksDir() + "/current";
|
||||||
|
globals.nixExprPath = getDefNixExprPath();
|
||||||
|
|
||||||
for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
|
for (Strings::iterator i = args.begin(); i != args.end(); ++i) {
|
||||||
string arg = *i;
|
string arg = *i;
|
||||||
|
@ -649,12 +670,20 @@ void run(Strings args)
|
||||||
op = opUpgrade;
|
op = opUpgrade;
|
||||||
else if (arg == "--query" || arg == "-q")
|
else if (arg == "--query" || arg == "-q")
|
||||||
op = opQuery;
|
op = opQuery;
|
||||||
|
else if (arg == "--import" || arg == "-I") /* !!! bad name */
|
||||||
|
op = opDefaultExpr;
|
||||||
else if (arg == "--link" || arg == "-l") {
|
else if (arg == "--link" || arg == "-l") {
|
||||||
++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.linkPath = absPath(*i);
|
||||||
}
|
}
|
||||||
|
else if (arg == "--file" || arg == "-f") {
|
||||||
|
++i;
|
||||||
|
if (i == args.end()) throw UsageError(
|
||||||
|
format("`%1%' requires an argument") % arg);
|
||||||
|
globals.nixExprPath = absPath(*i);
|
||||||
|
}
|
||||||
else if (arg == "--profile" || arg == "-p")
|
else if (arg == "--profile" || arg == "-p")
|
||||||
op = opSwitchProfile;
|
op = opSwitchProfile;
|
||||||
else if (arg[0] == '-')
|
else if (arg[0] == '-')
|
||||||
|
|
Loading…
Reference in a new issue