forked from lix-project/lix
Merge remote-tracking branch 'origin/master' into flakes
This commit is contained in:
commit
5ada0831cf
src
|
@ -269,16 +269,13 @@ bool isLink(const Path & path)
|
|||
}
|
||||
|
||||
|
||||
DirEntries readDirectory(const Path & path)
|
||||
DirEntries readDirectory(DIR *dir, const Path & path)
|
||||
{
|
||||
DirEntries entries;
|
||||
entries.reserve(64);
|
||||
|
||||
AutoCloseDir dir(opendir(path.c_str()));
|
||||
if (!dir) throw SysError(format("opening directory '%1%'") % path);
|
||||
|
||||
struct dirent * dirent;
|
||||
while (errno = 0, dirent = readdir(dir.get())) { /* sic */
|
||||
while (errno = 0, dirent = readdir(dir)) { /* sic */
|
||||
checkInterrupt();
|
||||
string name = dirent->d_name;
|
||||
if (name == "." || name == "..") continue;
|
||||
|
@ -295,6 +292,14 @@ DirEntries readDirectory(const Path & path)
|
|||
return entries;
|
||||
}
|
||||
|
||||
DirEntries readDirectory(const Path & path)
|
||||
{
|
||||
AutoCloseDir dir(opendir(path.c_str()));
|
||||
if (!dir) throw SysError(format("opening directory '%1%'") % path);
|
||||
|
||||
return readDirectory(dir.get(), path);
|
||||
}
|
||||
|
||||
|
||||
unsigned char getFileType(const Path & path)
|
||||
{
|
||||
|
@ -389,12 +394,14 @@ void writeLine(int fd, string s)
|
|||
}
|
||||
|
||||
|
||||
static void _deletePath(const Path & path, unsigned long long & bytesFreed)
|
||||
static void _deletePath(int parentfd, const Path & path, unsigned long long & bytesFreed)
|
||||
{
|
||||
checkInterrupt();
|
||||
|
||||
string name(baseNameOf(path));
|
||||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st) == -1) {
|
||||
if (fstatat(parentfd, name.c_str(), &st, AT_SYMLINK_NOFOLLOW) == -1) {
|
||||
if (errno == ENOENT) return;
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
}
|
||||
|
@ -406,20 +413,45 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed)
|
|||
/* Make the directory accessible. */
|
||||
const auto PERM_MASK = S_IRUSR | S_IWUSR | S_IXUSR;
|
||||
if ((st.st_mode & PERM_MASK) != PERM_MASK) {
|
||||
if (chmod(path.c_str(), st.st_mode | PERM_MASK) == -1)
|
||||
if (fchmodat(parentfd, name.c_str(), st.st_mode | PERM_MASK, 0) == -1)
|
||||
throw SysError(format("chmod '%1%'") % path);
|
||||
}
|
||||
|
||||
for (auto & i : readDirectory(path))
|
||||
_deletePath(path + "/" + i.name, bytesFreed);
|
||||
int fd = openat(parentfd, path.c_str(), O_RDONLY);
|
||||
if (!fd)
|
||||
throw SysError(format("opening directory '%1%'") % path);
|
||||
AutoCloseDir dir(fdopendir(fd));
|
||||
if (!dir)
|
||||
throw SysError(format("opening directory '%1%'") % path);
|
||||
for (auto & i : readDirectory(dir.get(), path))
|
||||
_deletePath(dirfd(dir.get()), path + "/" + i.name, bytesFreed);
|
||||
}
|
||||
|
||||
if (remove(path.c_str()) == -1) {
|
||||
int flags = S_ISDIR(st.st_mode) ? AT_REMOVEDIR : 0;
|
||||
if (unlinkat(parentfd, name.c_str(), flags) == -1) {
|
||||
if (errno == ENOENT) return;
|
||||
throw SysError(format("cannot unlink '%1%'") % path);
|
||||
}
|
||||
}
|
||||
|
||||
static void _deletePath(const Path & path, unsigned long long & bytesFreed)
|
||||
{
|
||||
Path dir = dirOf(path);
|
||||
if (dir == "")
|
||||
dir = "/";
|
||||
|
||||
AutoCloseFD dirfd(open(dir.c_str(), O_RDONLY));
|
||||
if (!dirfd) {
|
||||
// This really shouldn't fail silently, but it's left this way
|
||||
// for backwards compatibility.
|
||||
if (errno == ENOENT) return;
|
||||
|
||||
throw SysError(format("opening directory '%1%'") % path);
|
||||
}
|
||||
|
||||
_deletePath(dirfd.get(), path, bytesFreed);
|
||||
}
|
||||
|
||||
|
||||
void deletePath(const Path & path)
|
||||
{
|
||||
|
|
|
@ -718,28 +718,39 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
|
|||
while (true) {
|
||||
string lockToken = optimisticLockProfile(profile);
|
||||
|
||||
DrvInfos installedElems = queryInstalled(*globals.state, profile);
|
||||
DrvInfos newElems;
|
||||
DrvInfos workingElems = queryInstalled(*globals.state, profile);
|
||||
|
||||
for (auto & i : installedElems) {
|
||||
DrvName drvName(i.queryName());
|
||||
bool found = false;
|
||||
for (auto & j : selectors)
|
||||
/* !!! the repeated calls to followLinksToStorePath()
|
||||
are expensive, should pre-compute them. */
|
||||
if ((isPath(j) && globals.state->store->parseStorePath(i.queryOutPath()) == globals.state->store->followLinksToStorePath(j))
|
||||
|| DrvName(j).matches(drvName))
|
||||
{
|
||||
printInfo("uninstalling '%s'", i.queryName());
|
||||
found = true;
|
||||
break;
|
||||
for (auto & selector : selectors) {
|
||||
DrvInfos::iterator split = workingElems.begin();
|
||||
if (isPath(selector)) {
|
||||
StorePath selectorStorePath = globals.state->store->followLinksToStorePath(selector);
|
||||
split = std::partition(
|
||||
workingElems.begin(), workingElems.end(),
|
||||
[&selectorStorePath, globals](auto &elem) {
|
||||
return selectorStorePath != globals.state->store->parseStorePath(elem.queryOutPath());
|
||||
}
|
||||
if (!found) newElems.push_back(i);
|
||||
);
|
||||
} else {
|
||||
DrvName selectorName(selector);
|
||||
split = std::partition(
|
||||
workingElems.begin(), workingElems.end(),
|
||||
[&selectorName](auto &elem){
|
||||
DrvName elemName(elem.queryName());
|
||||
return !selectorName.matches(elemName);
|
||||
}
|
||||
);
|
||||
}
|
||||
if (split == workingElems.end())
|
||||
warn("selector '%s' matched no installed derivations", selector);
|
||||
for (auto removedElem = split; removedElem != workingElems.end(); removedElem++) {
|
||||
printInfo("uninstalling '%s'", removedElem->queryName());
|
||||
}
|
||||
workingElems.erase(split, workingElems.end());
|
||||
}
|
||||
|
||||
if (globals.dryRun) return;
|
||||
|
||||
if (createUserEnv(*globals.state, newElems,
|
||||
if (createUserEnv(*globals.state, workingElems,
|
||||
profile, settings.envKeepDerivations, lockToken)) break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,13 +205,15 @@ struct Common : InstallableCommand, MixProfile
|
|||
}
|
||||
}
|
||||
|
||||
BuildEnvironment getBuildEnvironment(ref<Store> store)
|
||||
std::pair<BuildEnvironment, std::string> getBuildEnvironment(ref<Store> store)
|
||||
{
|
||||
auto shellOutPath = getShellOutPath(store);
|
||||
|
||||
auto strPath = store->printStorePath(shellOutPath);
|
||||
|
||||
updateProfile(shellOutPath);
|
||||
|
||||
return readEnvironment(store->printStorePath(shellOutPath));
|
||||
return {readEnvironment(strPath), strPath};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -262,7 +264,7 @@ struct CmdDevShell : Common, MixEnvironment
|
|||
|
||||
void run(ref<Store> store) override
|
||||
{
|
||||
auto buildEnvironment = getBuildEnvironment(store);
|
||||
auto [buildEnvironment, gcroot] = getBuildEnvironment(store);
|
||||
|
||||
auto [rcFileFd, rcFilePath] = createTempFile("nix-shell");
|
||||
|
||||
|
@ -285,6 +287,8 @@ struct CmdDevShell : Common, MixEnvironment
|
|||
auto shell = getEnv("SHELL").value_or("bash");
|
||||
|
||||
setEnviron();
|
||||
// prevent garbage collection until shell exits
|
||||
setenv("NIX_GCROOT", gcroot.data(), 1);
|
||||
|
||||
auto args = Strings{std::string(baseNameOf(shell)), "--rcfile", rcFilePath};
|
||||
|
||||
|
@ -316,7 +320,7 @@ struct CmdPrintDevEnv : Common
|
|||
|
||||
void run(ref<Store> store) override
|
||||
{
|
||||
auto buildEnvironment = getBuildEnvironment(store);
|
||||
auto buildEnvironment = getBuildEnvironment(store).first;
|
||||
|
||||
stopProgressBar();
|
||||
|
||||
|
|
Loading…
Reference in a new issue