mirror of
https://github.com/NixOS/nix.git
synced 2025-11-27 04:30:59 +01:00
Merged to R9561; Fixed initial snapshot bug.
This commit is contained in:
parent
c28742f633
commit
1164d6a389
21 changed files with 1522 additions and 775 deletions
|
|
@ -298,18 +298,19 @@ static Expr prim_getEnv(EvalState & state, const ATermVector & args)
|
|||
return makeStr(getEnv(name));
|
||||
}
|
||||
|
||||
/* for debugging purposes. print the first arg on stdout (perhaps stderr should be used?)
|
||||
* and return the second
|
||||
|
||||
/* Evaluate the first expression, and print its abstract syntax tree
|
||||
on standard error. Then return the second expression. Useful for
|
||||
debugging.
|
||||
*/
|
||||
static Expr prim_trace(EvalState & state, const ATermVector & args)
|
||||
{
|
||||
//string str = evalStringNoCtx(state, args[0]);
|
||||
|
||||
Expr a = evalExpr(state, args[0]);
|
||||
printf("traced value: %s\n", atPrint(a).c_str());
|
||||
Expr e = evalExpr(state, args[0]);
|
||||
printMsg(lvlError, format("trace: %1%") % e);
|
||||
return evalExpr(state, args[1]);
|
||||
}
|
||||
|
||||
|
||||
static Expr prim_relativise(EvalState & state, const ATermVector & args)
|
||||
{
|
||||
PathSet context; /* !!! what to do? */
|
||||
|
|
|
|||
|
|
@ -27,6 +27,19 @@
|
|||
#include <grp.h>
|
||||
|
||||
|
||||
/* Includes required for chroot support. */
|
||||
#include "config.h"
|
||||
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
#if HAVE_SYS_MOUNT_H
|
||||
#include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#define CHROOT_ENABLED HAVE_CHROOT && HAVE_SYS_MOUNT_H && defined(MS_BIND)
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
using std::map;
|
||||
|
|
@ -585,6 +598,89 @@ void deletePathWrapped(const Path & path)
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/* Helper RAII class for automatically unmounting bind-mounts in
|
||||
chroots. */
|
||||
struct BindMount
|
||||
{
|
||||
Path source, target;
|
||||
Paths created;
|
||||
|
||||
BindMount()
|
||||
{
|
||||
}
|
||||
|
||||
BindMount(const Path & source, const Path & target)
|
||||
{
|
||||
bind(source, target);
|
||||
}
|
||||
|
||||
~BindMount()
|
||||
{
|
||||
try {
|
||||
unbind();
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
|
||||
void bind(const Path & source, const Path & target)
|
||||
{
|
||||
#if CHROOT_ENABLED
|
||||
debug(format("bind mounting `%1%' to `%2%'") % source % target);
|
||||
|
||||
this->source = source;
|
||||
this->target = target;
|
||||
|
||||
created = createDirs(target);
|
||||
|
||||
if (mount(source.c_str(), target.c_str(), "", MS_BIND, 0) == -1)
|
||||
throw SysError(format("bind mount from `%1%' to `%2%' failed") % source % target);
|
||||
#endif
|
||||
}
|
||||
|
||||
void unbind()
|
||||
{
|
||||
#if CHROOT_ENABLED
|
||||
if (source == "") return;
|
||||
|
||||
debug(format("unmount bind-mount `%1%'") % target);
|
||||
|
||||
/* Urgh. Unmount sometimes doesn't succeed right away because
|
||||
the mount point is still busy. It shouldn't be, because
|
||||
we've killed all the build processes by now (at least when
|
||||
using a build user; see the check in killUser()). But
|
||||
maybe this is because those processes are still zombies and
|
||||
are keeping some kernel structures busy (open files,
|
||||
current directories, etc.). So retry a few times
|
||||
(actually, a 1 second sleep is almost certainly enough for
|
||||
the zombies to be cleaned up). */
|
||||
unsigned int tries = 0;
|
||||
while (umount(target.c_str()) == -1) {
|
||||
if (errno == EBUSY && ++tries < 10) {
|
||||
printMsg(lvlError, format("unmounting `%1%' failed, retrying after 1 second...") % target);
|
||||
sleep(1);
|
||||
}
|
||||
else
|
||||
throw SysError(format("unmounting bind-mount `%1%' failed") % target);
|
||||
}
|
||||
|
||||
/* Get rid of the directories for the mount point created in
|
||||
bind(). */
|
||||
for (Paths::reverse_iterator i = created.rbegin(); i != created.rend(); ++i) {
|
||||
debug(format("deleting `%1%'") % *i);
|
||||
if (remove(i->c_str()) == -1)
|
||||
throw SysError(format("cannot unlink `%1%'") % *i);
|
||||
}
|
||||
|
||||
source = "";
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class DerivationGoal : public Goal
|
||||
{
|
||||
private:
|
||||
|
|
@ -635,6 +731,17 @@ private:
|
|||
Pipe toHook;
|
||||
Pipe fromHook;
|
||||
|
||||
/* Whether we're currently doing a chroot build. */
|
||||
bool useChroot;
|
||||
|
||||
/* A RAII object to delete the chroot directory. */
|
||||
boost::shared_ptr<AutoDelete> autoDelChroot;
|
||||
|
||||
/* In chroot builds, the list of bind mounts currently active.
|
||||
The destructor of BindMount will cause the binds to be
|
||||
unmounted. */
|
||||
list<boost::shared_ptr<BindMount> > bindMounts;
|
||||
|
||||
typedef void (DerivationGoal::*GoalState)();
|
||||
GoalState state;
|
||||
|
||||
|
|
@ -690,7 +797,7 @@ private:
|
|||
void openLogFile();
|
||||
|
||||
/* Common initialisation to be performed in child processes (i.e.,
|
||||
both in builders and in build hooks. */
|
||||
both in builders and in build hooks). */
|
||||
void initChild();
|
||||
|
||||
/* Delete the temporary directory, if we have one. */
|
||||
|
|
@ -1038,6 +1145,9 @@ void DerivationGoal::buildDone()
|
|||
|
||||
deleteTmpDir(true);
|
||||
|
||||
/* In chroot builds, unmount the bind mounts ASAP. */
|
||||
bindMounts.clear(); /* the destructors will do the rest */
|
||||
|
||||
/* Compute the FS closure of the outputs and register them as
|
||||
being valid. */
|
||||
computeClosure();
|
||||
|
|
@ -1208,7 +1318,7 @@ DerivationGoal::HookReply DerivationGoal::tryBuildHook()
|
|||
throw SysError(format("executing `%1%'") % buildHook);
|
||||
|
||||
} catch (std::exception & e) {
|
||||
std::cerr << format("build hook error: %1%\n") % e.what();
|
||||
std::cerr << format("build hook error: %1%") % e.what() << std::endl;
|
||||
}
|
||||
quickExit(1);
|
||||
}
|
||||
|
|
@ -1596,6 +1706,56 @@ void DerivationGoal::startBuilder()
|
|||
% buildUser.getGID() % nixStore);
|
||||
}
|
||||
|
||||
|
||||
/* Are we doing a chroot build? */
|
||||
useChroot = queryBoolSetting("build-use-chroot", false);
|
||||
Path tmpRootDir;
|
||||
|
||||
if (useChroot) {
|
||||
#if CHROOT_ENABLED
|
||||
/* Create a temporary directory in which we set up the chroot
|
||||
environment using bind-mounts.
|
||||
|
||||
!!! Big danger here: since we're doing this in /tmp, there
|
||||
is a risk that the admin does something like "rm -rf
|
||||
/tmp/chroot-nix-*" to clean up aborted builds, and if some
|
||||
of the bind-mounts are still active, then "rm -rf" will
|
||||
happily recurse into those mount points (thereby deleting,
|
||||
say, /nix/store). Ideally, tmpRootDir should be created in
|
||||
some special location (maybe in /nix/var/nix) where Nix
|
||||
takes care of unmounting / deleting old chroots
|
||||
automatically. */
|
||||
tmpRootDir = createTempDir("", "chroot-nix");
|
||||
|
||||
/* Clean up the chroot directory automatically, but don't
|
||||
recurse; that would be very very bad if the unmount of a
|
||||
bind-mount fails. Instead BindMount::unbind() unmounts and
|
||||
deletes exactly those directories that it created to
|
||||
produce the mount point, so that after all the BindMount
|
||||
destructors have run, tmpRootDir should be empty. */
|
||||
autoDelChroot = boost::shared_ptr<AutoDelete>(new AutoDelete(tmpRootDir, false));
|
||||
|
||||
printMsg(lvlChatty, format("setting up chroot environment in `%1%'") % tmpRootDir);
|
||||
|
||||
Paths defaultDirs;
|
||||
defaultDirs.push_back("/dev");
|
||||
defaultDirs.push_back("/proc");
|
||||
Paths dirsInChroot = querySetting("build-chroot-dirs", defaultDirs);
|
||||
|
||||
dirsInChroot.push_front(nixStore);
|
||||
dirsInChroot.push_front(tmpDir);
|
||||
|
||||
/* Push BindMounts at the front of the list so that they get
|
||||
unmounted in LIFO order. (!!! Does the C++ standard
|
||||
guarantee that list elements are destroyed in order?) */
|
||||
for (Paths::iterator i = dirsInChroot.begin(); i != dirsInChroot.end(); ++i)
|
||||
bindMounts.push_front(boost::shared_ptr<BindMount>(new BindMount(*i, tmpRootDir + *i)));
|
||||
|
||||
#else
|
||||
throw Error("chroot builds are not supported on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Run the builder. */
|
||||
printMsg(lvlChatty, format("executing builder `%1%'") %
|
||||
|
|
@ -1621,6 +1781,17 @@ void DerivationGoal::startBuilder()
|
|||
|
||||
try { /* child */
|
||||
|
||||
#if CHROOT_ENABLED
|
||||
/* If building in a chroot, do the chroot right away.
|
||||
initChild() will do a chdir() to the temporary build
|
||||
directory to make sure the current directory is in the
|
||||
chroot. (Actually the order doesn't matter, since due
|
||||
to the bind mount tmpDir and tmpRootDit/tmpDir are the
|
||||
same directories.) */
|
||||
if (useChroot && chroot(tmpRootDir.c_str()) == -1)
|
||||
throw SysError(format("cannot change root directory to `%1%'") % tmpRootDir);
|
||||
#endif
|
||||
|
||||
initChild();
|
||||
|
||||
/* Fill in the environment. */
|
||||
|
|
@ -1684,7 +1855,7 @@ void DerivationGoal::startBuilder()
|
|||
% drv.builder);
|
||||
|
||||
} catch (std::exception & e) {
|
||||
std::cerr << format("build error: %1%\n") % e.what();
|
||||
std::cerr << format("build error: %1%") % e.what() << std::endl;
|
||||
}
|
||||
quickExit(1);
|
||||
}
|
||||
|
|
@ -1916,13 +2087,6 @@ void DerivationGoal::computeClosure()
|
|||
state_stateReferences,
|
||||
drvPath, 0);
|
||||
|
||||
//Commit state (we only include our own state in the rivisionMapping (but other build component states might have been changed !!!! TODO)
|
||||
RevisionClosure rivisionMapping;
|
||||
rivisionMapping[statePath] = commitStatePathTxn(txn, statePath);
|
||||
|
||||
//Save the new revision
|
||||
setStateRevisionsTxn(txn, rivisionMapping, statePath, "Initial build revision.");
|
||||
|
||||
//Convert stateInfo from drv to DB format
|
||||
//And set all interval-ed paths to zero to begin with
|
||||
DerivationStateOutputDirs stateOutputDirs = drv.stateOutputDirs;
|
||||
|
|
@ -1953,6 +2117,13 @@ void DerivationGoal::computeClosure()
|
|||
//register state options that may change
|
||||
DerivationStateOutput drvso = drv.stateOutputs["state"];
|
||||
setStateOptionsTxn(txn, statePath, queryCallingUsername(), "nixbld", 700, drvso.runtimeStateArgs);
|
||||
|
||||
//Commit state (we only include our own state in the rivisionMapping (but other build component states might have been changed !!!! TODO)
|
||||
RevisionClosure rivisionMapping;
|
||||
rivisionMapping[statePath] = commitStatePathTxn(txn, statePath);
|
||||
|
||||
//Save the new revision
|
||||
setStateRevisionsTxn(txn, rivisionMapping, statePath, "Initial build revision.");
|
||||
|
||||
//Shared state
|
||||
Path sharedState = drv.stateOutputs.find("state")->second.sharedState;
|
||||
|
|
@ -2332,7 +2503,7 @@ void SubstitutionGoal::tryToRun()
|
|||
throw SysError(format("executing `%1%'") % sub);
|
||||
|
||||
} catch (std::exception & e) {
|
||||
std::cerr << format("substitute error: %1%\n") % e.what();
|
||||
std::cerr << format("substitute error: %1%") % e.what() << std::endl;
|
||||
}
|
||||
quickExit(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,13 +185,15 @@ Snapshots commitStatePathTxn(const Transaction & txn, const Path & statePath)
|
|||
CommitIntervals intervals = getStatePathsIntervalTxn(txn, statePath);
|
||||
|
||||
Snapshots revisions_list;
|
||||
|
||||
|
||||
for (StateInfos::const_iterator i = infos.begin(); i != infos.end(); ++i){
|
||||
|
||||
string thisdir = (*i).path;
|
||||
string type = (*i).type;
|
||||
unsigned int interval = (*i).interval;
|
||||
|
||||
//printMsg(lvlError, format("maybe ssing %1% %2%") % thisdir % type);
|
||||
|
||||
if(type == "none"){
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -319,19 +319,19 @@ void makePathReadOnly(const Path & path)
|
|||
}
|
||||
|
||||
|
||||
static Path tempName(const Path & tmpRoot)
|
||||
static Path tempName(const Path & tmpRoot, const Path & prefix)
|
||||
{
|
||||
static int counter = 0;
|
||||
Path tmpRoot2 = canonPath(tmpRoot.empty() ? getEnv("TMPDIR", "/tmp") : tmpRoot, true);
|
||||
return (format("%1%/nix-%2%-%3%") % tmpRoot2 % getpid() % counter++).str();
|
||||
return (format("%1%/%2%-%3%-%4%") % tmpRoot2 % prefix % getpid() % counter++).str();
|
||||
}
|
||||
|
||||
|
||||
Path createTempDir(const Path & tmpRoot)
|
||||
Path createTempDir(const Path & tmpRoot, const Path & prefix)
|
||||
{
|
||||
while (1) {
|
||||
checkInterrupt();
|
||||
Path tmpDir = tempName(tmpRoot);
|
||||
Path tmpDir = tempName(tmpRoot, prefix);
|
||||
if (mkdir(tmpDir.c_str(), 0777) == 0) {
|
||||
/* Explicitly set the group of the directory. This is to
|
||||
work around around problems caused by BSD's group
|
||||
|
|
@ -350,13 +350,16 @@ Path createTempDir(const Path & tmpRoot)
|
|||
}
|
||||
}
|
||||
|
||||
void createDirs(const Path & path)
|
||||
Paths createDirs(const Path & path)
|
||||
{
|
||||
if (path == "/") return;
|
||||
createDirs(dirOf(path));
|
||||
if (!pathExists(path))
|
||||
if (path == "/") return Paths();
|
||||
Paths created = createDirs(dirOf(path));
|
||||
if (!pathExists(path)) {
|
||||
if (mkdir(path.c_str(), 0777) == -1)
|
||||
throw SysError(format("creating directory `%1%'") % path);
|
||||
created.push_back(path);
|
||||
}
|
||||
return created;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -511,14 +514,25 @@ string drainFD(int fd)
|
|||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
AutoDelete::AutoDelete(const string & p) : path(p)
|
||||
AutoDelete::AutoDelete(const string & p, bool recursive) : path(p)
|
||||
{
|
||||
del = true;
|
||||
this->recursive = recursive;
|
||||
}
|
||||
|
||||
AutoDelete::~AutoDelete()
|
||||
{
|
||||
if (del) deletePath(path);
|
||||
try {
|
||||
if (del)
|
||||
if (recursive)
|
||||
deletePath(path);
|
||||
else {
|
||||
if (remove(path.c_str()) == -1)
|
||||
throw SysError(format("cannot unlink `%1%'") % path);
|
||||
}
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
|
||||
void AutoDelete::cancel()
|
||||
|
|
@ -754,10 +768,10 @@ void killUser(uid_t uid)
|
|||
if (errno != EINTR)
|
||||
throw SysError(format("cannot kill processes for uid `%1%'") % uid);
|
||||
}
|
||||
|
||||
|
||||
} catch (std::exception & e) {
|
||||
std::cerr << format("killing processes beloging to uid `%1%': %1%\n")
|
||||
% uid % e.what();
|
||||
std::cerr << format("killing processes beloging to uid `%1%': %1%")
|
||||
% uid % e.what() << std::endl;
|
||||
quickExit(1);
|
||||
}
|
||||
quickExit(0);
|
||||
|
|
@ -812,7 +826,7 @@ string runProgram(Path program, bool searchPath, const Strings & args)
|
|||
throw SysError(format("executing `%1%'") % program);
|
||||
|
||||
} catch (std::exception & e) {
|
||||
std::cerr << "error: " << e.what() << std::endl;
|
||||
std::cerr << "error: " << e.what() << std::endl; //TODO does not give the full error message
|
||||
}
|
||||
quickExit(1);
|
||||
}
|
||||
|
|
@ -1201,21 +1215,6 @@ bool IsSymlink(const string FileName)
|
|||
return (S_ISLNK(my_stat.st_mode) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
string getCallingUserName()
|
||||
{
|
||||
//Linux
|
||||
Strings empty;
|
||||
string username = runProgram("whoami", true, empty); //the username of the user that is trying to build the component
|
||||
//TODO Can be faked, so this is clearly unsafe ... :(
|
||||
//Remove the trailing \n
|
||||
int pos = username.find("\n",0);
|
||||
username.erase(pos,1);
|
||||
|
||||
return username;
|
||||
}
|
||||
*/
|
||||
|
||||
/* adds the second PathSet after the first, but removing doubles from the second (union)
|
||||
* (We assume the first PathSet has no duplicates)
|
||||
* UNTESTED !!!!!!!!!!!!!!
|
||||
|
|
@ -1321,8 +1320,15 @@ void symlinkPath(const Path & existingDir, const Path & newLinkName) //TODO bool
|
|||
* We do -snf for:
|
||||
* -s : symlinking
|
||||
* -f : To remove existing destination files (this does NOT always overwrite the newLinkName !!!!)
|
||||
* -n : Treat destination that is a symlink to a directory as if it were a normal file (This makes sure
|
||||
* that newLinkName is really overwritten)
|
||||
* -n : Treat destination that is a symlink to a directory as if it were a normal file:
|
||||
* When the destination is an actual directory (not a symlink to one), there is no ambiguity.
|
||||
* The link is created in that directory. But when the specified destination is a symlink to a directory,
|
||||
* there are two ways to treat the user's request. ln can treat the destination just as it would a normal
|
||||
* directory and create the link in it. On the other hand, the destination can be viewed as a non-directory
|
||||
* - as the symlink itself. In that case, ln must delete or backup that symlink before creating the new link.
|
||||
* The default is to treat a destination that is a symlink to a directory just like a directory.
|
||||
*
|
||||
* ((This makes sure that newLinkName is really overwritten)
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -79,10 +79,11 @@ void deletePath(const Path & path, unsigned long long & bytesFreed);
|
|||
void makePathReadOnly(const Path & path);
|
||||
|
||||
/* Create a temporary directory. */
|
||||
Path createTempDir(const Path & tmpRoot = "");
|
||||
Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix");
|
||||
|
||||
/* Create a directory and all its parents, if necessary. */
|
||||
void createDirs(const Path & path);
|
||||
/* Create a directory and all its parents, if necessary. Returns the
|
||||
list of created directories, in order of creation. */
|
||||
Paths createDirs(const Path & path);
|
||||
|
||||
/* Create a file and write the given text to it. The file is written
|
||||
in binary mode (i.e., no end-of-line conversions). The path should
|
||||
|
|
@ -175,8 +176,9 @@ class AutoDelete
|
|||
{
|
||||
Path path;
|
||||
bool del;
|
||||
bool recursive;
|
||||
public:
|
||||
AutoDelete(const Path & p);
|
||||
AutoDelete(const Path & p, bool recursive = true);
|
||||
~AutoDelete();
|
||||
void cancel();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,8 +63,6 @@ Query flags:
|
|||
--out-path: print path of derivation output
|
||||
--description: print description
|
||||
--meta: print all meta attributes (only with --xml)
|
||||
--prebuilt-only: only show derivations whose prebuilt binaries are
|
||||
available on this machine or are downloadable
|
||||
|
||||
Options:
|
||||
|
||||
|
|
@ -74,3 +72,5 @@ Options:
|
|||
--keep-failed / -K: keep temporary directories of failed builds
|
||||
--preserve-installed: do not replace currently installed versions in `-i'
|
||||
--system-filter SYSTEM: only use derivations for specified platform
|
||||
--prebuilt-only / -b: only use derivations whose prebuilt binaries are
|
||||
available on this machine or are downloadable
|
||||
|
|
|
|||
|
|
@ -49,8 +49,9 @@ struct InstallSourceInfo
|
|||
Path nixExprPath; /* for srcNixExprDrvs, srcNixExprs */
|
||||
Path profile; /* for srcProfile */
|
||||
string systemFilter; /* for srcNixExprDrvs */
|
||||
bool prebuiltOnly;
|
||||
ATermMap autoArgs;
|
||||
InstallSourceInfo() : autoArgs() { };
|
||||
InstallSourceInfo() : prebuiltOnly(false) { };
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -96,6 +97,8 @@ static bool parseInstallSourceOptions(Globals & globals,
|
|||
}
|
||||
else if (arg == "--attr" || arg == "-A")
|
||||
globals.instSource.type = srcAttrPath;
|
||||
else if (arg == "--prebuilt-only" || arg == "-b")
|
||||
globals.instSource.prebuiltOnly = true;
|
||||
else return false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -339,9 +342,16 @@ static int comparePriorities(EvalState & state,
|
|||
}
|
||||
|
||||
|
||||
static DrvInfos filterBySelector(EvalState & state,
|
||||
const DrvInfos & allElems,
|
||||
const Strings & args, bool newestOnly)
|
||||
static bool isPrebuilt(EvalState & state, const DrvInfo & elem)
|
||||
{
|
||||
return
|
||||
store->isValidPath(elem.queryOutPath(state)) ||
|
||||
store->hasSubstitutes(elem.queryOutPath(state));
|
||||
}
|
||||
|
||||
|
||||
static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems,
|
||||
const Strings & args, bool newestOnly, bool prebuiltOnly)
|
||||
{
|
||||
DrvNames selectors = drvNamesFromArgs(args);
|
||||
|
||||
|
|
@ -360,7 +370,8 @@ static DrvInfos filterBySelector(EvalState & state,
|
|||
DrvName drvName(j->name);
|
||||
if (i->matches(drvName)) {
|
||||
i->hits++;
|
||||
matches.push_back(std::pair<DrvInfo, unsigned int>(*j, n));
|
||||
if (!prebuiltOnly || isPrebuilt(state, *j))
|
||||
matches.push_back(std::pair<DrvInfo, unsigned int>(*j, n));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -450,7 +461,8 @@ static void queryInstSources(EvalState & state,
|
|||
loadDerivations(state, instSource.nixExprPath,
|
||||
instSource.systemFilter, instSource.autoArgs, "", allElems);
|
||||
|
||||
elems = filterBySelector(state, allElems, args, newestOnly);
|
||||
elems = filterBySelector(state, allElems, args,
|
||||
newestOnly, instSource.prebuiltOnly);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -518,7 +530,7 @@ static void queryInstSources(EvalState & state,
|
|||
case srcProfile: {
|
||||
elems = filterBySelector(state,
|
||||
queryInstalled(state, instSource.profile),
|
||||
args, newestOnly);
|
||||
args, newestOnly, instSource.prebuiltOnly);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1152,7 +1164,7 @@ static void opQuery(Globals & globals,
|
|||
|
||||
DrvInfos elems = filterBySelector(globals.state,
|
||||
source == sInstalled ? installedElems : availElems,
|
||||
remaining, false);
|
||||
remaining, false, prebuiltOnly);
|
||||
|
||||
DrvInfos & otherElems(source == sInstalled ? availElems : installedElems);
|
||||
|
||||
|
|
@ -1193,12 +1205,6 @@ static void opQuery(Globals & globals,
|
|||
/* For XML output. */
|
||||
XMLAttrs attrs;
|
||||
|
||||
if (prebuiltOnly) {
|
||||
if (!store->isValidPath(i->queryOutPath(globals.state)) &&
|
||||
!store->hasSubstitutes(i->queryOutPath(globals.state)))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (printStatus) {
|
||||
bool hasSubs = store->hasSubstitutes(i->queryOutPath(globals.state));
|
||||
bool isInstalled = installed.find(i->queryOutPath(globals.state)) != installed.end();
|
||||
|
|
|
|||
|
|
@ -197,7 +197,6 @@ static void revertToRevision(Strings opFlags, Strings opArgs)
|
|||
static void queryAvailableStateRevisions(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
Path statePath;
|
||||
|
||||
if(store->isValidStatePath(*(opArgs.begin())))
|
||||
statePath = *(opArgs.begin());
|
||||
else{
|
||||
|
|
@ -292,7 +291,18 @@ static void opShowSharedPaths(Strings opFlags, Strings opArgs)
|
|||
|
||||
static void opUnshare(Strings opFlags, Strings opArgs)
|
||||
{
|
||||
Path statePath = *(opArgs.begin());
|
||||
Path statePath;
|
||||
if(store->isValidStatePath(*(opArgs.begin())))
|
||||
statePath = *(opArgs.begin());
|
||||
else{
|
||||
Path componentPath;
|
||||
string binary;
|
||||
string derivationPath;
|
||||
bool isStateComponent;
|
||||
Strings program_args;
|
||||
getPathInfo_andCheckArgs(opFlags, opArgs, componentPath, statePath, binary, derivationPath, isStateComponent, program_args);
|
||||
}
|
||||
|
||||
if(!store->isValidStatePath(statePath))
|
||||
throw UsageError(format("Path '%1%' is not a valid state path.") % statePath);
|
||||
|
||||
|
|
@ -784,10 +794,10 @@ void run(Strings args)
|
|||
|
||||
*/
|
||||
|
||||
//Manipulate options....
|
||||
//Manipulate options TODO only allow for root user ...
|
||||
else if (arg.substr(0,13) == "--identifier=")
|
||||
stateIdentifier = arg.substr(13,arg.length());
|
||||
else if (arg.substr(0,7) == "--user=")
|
||||
else if (arg.substr(0,7) == "--nix-user=")
|
||||
username = arg.substr(7,arg.length());
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -240,8 +240,8 @@ static void performOp(Source & from, Sink & to, unsigned int op)
|
|||
}
|
||||
#endif
|
||||
|
||||
case wopIsValidPath: {
|
||||
Path path = readStorePath(from);
|
||||
case wopIsValidPath: { //we do a readString at isValidXXXX
|
||||
Path path = readString(from);
|
||||
startWork();
|
||||
bool result = store->isValidPath(path);
|
||||
stopWork();
|
||||
|
|
@ -250,7 +250,7 @@ static void performOp(Source & from, Sink & to, unsigned int op)
|
|||
}
|
||||
|
||||
case wopIsValidStatePath: {
|
||||
Path path = readStatePath(from);
|
||||
Path path = readString(from);
|
||||
startWork();
|
||||
bool result = store->isValidStatePath(path);
|
||||
stopWork();
|
||||
|
|
@ -259,7 +259,7 @@ static void performOp(Source & from, Sink & to, unsigned int op)
|
|||
}
|
||||
|
||||
case wopIsValidComponentOrStatePath: {
|
||||
Path path = readStoreOrStatePath(from);
|
||||
Path path = readString(from);
|
||||
startWork();
|
||||
bool result = store->isValidComponentOrStatePath(path);
|
||||
stopWork();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue