forked from lix-project/lix
Merge remote-tracking branch 'origin/master' into flakes
This commit is contained in:
commit
5ada0831cf
|
@ -269,16 +269,13 @@ bool isLink(const Path & path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DirEntries readDirectory(const Path & path)
|
DirEntries readDirectory(DIR *dir, const Path & path)
|
||||||
{
|
{
|
||||||
DirEntries entries;
|
DirEntries entries;
|
||||||
entries.reserve(64);
|
entries.reserve(64);
|
||||||
|
|
||||||
AutoCloseDir dir(opendir(path.c_str()));
|
|
||||||
if (!dir) throw SysError(format("opening directory '%1%'") % path);
|
|
||||||
|
|
||||||
struct dirent * dirent;
|
struct dirent * dirent;
|
||||||
while (errno = 0, dirent = readdir(dir.get())) { /* sic */
|
while (errno = 0, dirent = readdir(dir)) { /* sic */
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
string name = dirent->d_name;
|
string name = dirent->d_name;
|
||||||
if (name == "." || name == "..") continue;
|
if (name == "." || name == "..") continue;
|
||||||
|
@ -295,6 +292,14 @@ DirEntries readDirectory(const Path & path)
|
||||||
return entries;
|
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)
|
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();
|
checkInterrupt();
|
||||||
|
|
||||||
|
string name(baseNameOf(path));
|
||||||
|
|
||||||
struct stat st;
|
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;
|
if (errno == ENOENT) return;
|
||||||
throw SysError(format("getting status of '%1%'") % path);
|
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. */
|
/* Make the directory accessible. */
|
||||||
const auto PERM_MASK = S_IRUSR | S_IWUSR | S_IXUSR;
|
const auto PERM_MASK = S_IRUSR | S_IWUSR | S_IXUSR;
|
||||||
if ((st.st_mode & PERM_MASK) != PERM_MASK) {
|
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);
|
throw SysError(format("chmod '%1%'") % path);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & i : readDirectory(path))
|
int fd = openat(parentfd, path.c_str(), O_RDONLY);
|
||||||
_deletePath(path + "/" + i.name, bytesFreed);
|
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;
|
if (errno == ENOENT) return;
|
||||||
throw SysError(format("cannot unlink '%1%'") % path);
|
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)
|
void deletePath(const Path & path)
|
||||||
{
|
{
|
||||||
|
|
|
@ -718,28 +718,39 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
|
||||||
while (true) {
|
while (true) {
|
||||||
string lockToken = optimisticLockProfile(profile);
|
string lockToken = optimisticLockProfile(profile);
|
||||||
|
|
||||||
DrvInfos installedElems = queryInstalled(*globals.state, profile);
|
DrvInfos workingElems = queryInstalled(*globals.state, profile);
|
||||||
DrvInfos newElems;
|
|
||||||
|
|
||||||
for (auto & i : installedElems) {
|
for (auto & selector : selectors) {
|
||||||
DrvName drvName(i.queryName());
|
DrvInfos::iterator split = workingElems.begin();
|
||||||
bool found = false;
|
if (isPath(selector)) {
|
||||||
for (auto & j : selectors)
|
StorePath selectorStorePath = globals.state->store->followLinksToStorePath(selector);
|
||||||
/* !!! the repeated calls to followLinksToStorePath()
|
split = std::partition(
|
||||||
are expensive, should pre-compute them. */
|
workingElems.begin(), workingElems.end(),
|
||||||
if ((isPath(j) && globals.state->store->parseStorePath(i.queryOutPath()) == globals.state->store->followLinksToStorePath(j))
|
[&selectorStorePath, globals](auto &elem) {
|
||||||
|| DrvName(j).matches(drvName))
|
return selectorStorePath != globals.state->store->parseStorePath(elem.queryOutPath());
|
||||||
{
|
}
|
||||||
printInfo("uninstalling '%s'", i.queryName());
|
);
|
||||||
found = true;
|
} else {
|
||||||
break;
|
DrvName selectorName(selector);
|
||||||
}
|
split = std::partition(
|
||||||
if (!found) newElems.push_back(i);
|
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 (globals.dryRun) return;
|
||||||
|
|
||||||
if (createUserEnv(*globals.state, newElems,
|
if (createUserEnv(*globals.state, workingElems,
|
||||||
profile, settings.envKeepDerivations, lockToken)) break;
|
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 shellOutPath = getShellOutPath(store);
|
||||||
|
|
||||||
|
auto strPath = store->printStorePath(shellOutPath);
|
||||||
|
|
||||||
updateProfile(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
|
void run(ref<Store> store) override
|
||||||
{
|
{
|
||||||
auto buildEnvironment = getBuildEnvironment(store);
|
auto [buildEnvironment, gcroot] = getBuildEnvironment(store);
|
||||||
|
|
||||||
auto [rcFileFd, rcFilePath] = createTempFile("nix-shell");
|
auto [rcFileFd, rcFilePath] = createTempFile("nix-shell");
|
||||||
|
|
||||||
|
@ -285,6 +287,8 @@ struct CmdDevShell : Common, MixEnvironment
|
||||||
auto shell = getEnv("SHELL").value_or("bash");
|
auto shell = getEnv("SHELL").value_or("bash");
|
||||||
|
|
||||||
setEnviron();
|
setEnviron();
|
||||||
|
// prevent garbage collection until shell exits
|
||||||
|
setenv("NIX_GCROOT", gcroot.data(), 1);
|
||||||
|
|
||||||
auto args = Strings{std::string(baseNameOf(shell)), "--rcfile", rcFilePath};
|
auto args = Strings{std::string(baseNameOf(shell)), "--rcfile", rcFilePath};
|
||||||
|
|
||||||
|
@ -316,7 +320,7 @@ struct CmdPrintDevEnv : Common
|
||||||
|
|
||||||
void run(ref<Store> store) override
|
void run(ref<Store> store) override
|
||||||
{
|
{
|
||||||
auto buildEnvironment = getBuildEnvironment(store);
|
auto buildEnvironment = getBuildEnvironment(store).first;
|
||||||
|
|
||||||
stopProgressBar();
|
stopProgressBar();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue