aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2022-03-25 19:40:52 +0000
committerJohn Ericson <John.Ericson@Obsidian.Systems>2022-03-25 19:40:52 +0000
commitff2a8ccfe176fa3e075ed8925a371eeb17e627e6 (patch)
tree7c20ce8a8ae5370f6fc078fa26888c7417f47c7a /src/libutil
parent938650700fafe76e3755982d670855fed3db35c6 (diff)
parent0dc2974930df57cac6673c02e9bc6eb6fd16ba48 (diff)
Merge branch 'path-info' into ca-drv-exotic
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/archive.cc19
-rw-r--r--src/libutil/archive.hh4
-rw-r--r--src/libutil/error.hh1
-rw-r--r--src/libutil/experimental-features.cc1
-rw-r--r--src/libutil/experimental-features.hh3
-rw-r--r--src/libutil/finally.hh7
-rw-r--r--src/libutil/tarfile.cc26
-rw-r--r--src/libutil/tarfile.hh3
-rw-r--r--src/libutil/util.cc40
9 files changed, 71 insertions, 33 deletions
diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc
index eda004756..30b471af5 100644
--- a/src/libutil/archive.cc
+++ b/src/libutil/archive.cc
@@ -64,11 +64,12 @@ static void dumpContents(const Path & path, off_t size,
}
-static void dump(const Path & path, Sink & sink, PathFilter & filter)
+static time_t dump(const Path & path, Sink & sink, PathFilter & filter)
{
checkInterrupt();
auto st = lstat(path);
+ time_t result = st.st_mtime;
sink << "(";
@@ -103,7 +104,10 @@ static void dump(const Path & path, Sink & sink, PathFilter & filter)
for (auto & i : unhacked)
if (filter(path + "/" + i.first)) {
sink << "entry" << "(" << "name" << i.first << "node";
- dump(path + "/" + i.second, sink, filter);
+ auto tmp_mtime = dump(path + "/" + i.second, sink, filter);
+ if (tmp_mtime > result) {
+ result = tmp_mtime;
+ }
sink << ")";
}
}
@@ -114,13 +118,20 @@ static void dump(const Path & path, Sink & sink, PathFilter & filter)
else throw Error("file '%1%' has an unsupported type", path);
sink << ")";
+
+ return result;
}
-void dumpPath(const Path & path, Sink & sink, PathFilter & filter)
+time_t dumpPathAndGetMtime(const Path & path, Sink & sink, PathFilter & filter)
{
sink << narVersionMagic1;
- dump(path, sink, filter);
+ return dump(path, sink, filter);
+}
+
+void dumpPath(const Path & path, Sink & sink, PathFilter & filter)
+{
+ dumpPathAndGetMtime(path, sink, filter);
}
diff --git a/src/libutil/archive.hh b/src/libutil/archive.hh
index fca351605..79ce08df0 100644
--- a/src/libutil/archive.hh
+++ b/src/libutil/archive.hh
@@ -48,6 +48,10 @@ namespace nix {
void dumpPath(const Path & path, Sink & sink,
PathFilter & filter = defaultPathFilter);
+/* Same as `void dumpPath()`, but returns the last modified date of the path */
+time_t dumpPathAndGetMtime(const Path & path, Sink & sink,
+ PathFilter & filter = defaultPathFilter);
+
void dumpString(std::string_view s, Sink & sink);
/* FIXME: fix this API, it sucks. */
diff --git a/src/libutil/error.hh b/src/libutil/error.hh
index cb6532587..a7cd08d74 100644
--- a/src/libutil/error.hh
+++ b/src/libutil/error.hh
@@ -54,6 +54,7 @@ typedef enum {
lvlVomit
} Verbosity;
+/* adjust Pos::origin bit width when adding stuff here */
typedef enum {
foFile,
foStdin,
diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc
index b49f47e1d..01f318fa3 100644
--- a/src/libutil/experimental-features.cc
+++ b/src/libutil/experimental-features.cc
@@ -11,6 +11,7 @@ std::map<ExperimentalFeature, std::string> stringifiedXpFeatures = {
{ Xp::NixCommand, "nix-command" },
{ Xp::RecursiveNix, "recursive-nix" },
{ Xp::NoUrlLiterals, "no-url-literals" },
+ { Xp::FetchClosure, "fetch-closure" },
};
const std::optional<ExperimentalFeature> parseExperimentalFeature(const std::string_view & name)
diff --git a/src/libutil/experimental-features.hh b/src/libutil/experimental-features.hh
index 291a58e32..b5140dcfe 100644
--- a/src/libutil/experimental-features.hh
+++ b/src/libutil/experimental-features.hh
@@ -19,7 +19,8 @@ enum struct ExperimentalFeature
Flakes,
NixCommand,
RecursiveNix,
- NoUrlLiterals
+ NoUrlLiterals,
+ FetchClosure,
};
/**
diff --git a/src/libutil/finally.hh b/src/libutil/finally.hh
index 7760cfe9a..dee2e8d2f 100644
--- a/src/libutil/finally.hh
+++ b/src/libutil/finally.hh
@@ -1,14 +1,13 @@
#pragma once
-#include <functional>
-
/* A trivial class to run a function at the end of a scope. */
+template<typename Fn>
class Finally
{
private:
- std::function<void()> fun;
+ Fn fun;
public:
- Finally(std::function<void()> fun) : fun(fun) { }
+ Finally(Fn fun) : fun(std::move(fun)) { }
~Finally() { fun(); }
};
diff --git a/src/libutil/tarfile.cc b/src/libutil/tarfile.cc
index 790bc943a..a7db58559 100644
--- a/src/libutil/tarfile.cc
+++ b/src/libutil/tarfile.cc
@@ -39,28 +39,30 @@ void TarArchive::check(int err, const std::string & reason)
throw Error(reason, archive_error_string(this->archive));
}
-TarArchive::TarArchive(Source & source, bool raw)
- : source(&source), buffer(4096)
+TarArchive::TarArchive(Source & source, bool raw) : buffer(4096)
{
- init();
- if (!raw)
+ this->archive = archive_read_new();
+ this->source = &source;
+
+ if (!raw) {
+ archive_read_support_filter_all(archive);
archive_read_support_format_all(archive);
- else
+ } else {
+ archive_read_support_filter_all(archive);
archive_read_support_format_raw(archive);
+ archive_read_support_format_empty(archive);
+ }
check(archive_read_open(archive, (void *)this, callback_open, callback_read, callback_close), "Failed to open archive (%s)");
}
+
TarArchive::TarArchive(const Path & path)
{
- init();
- archive_read_support_format_all(archive);
- check(archive_read_open_filename(archive, path.c_str(), 16384), "failed to open archive: %s");
-}
+ this->archive = archive_read_new();
-void TarArchive::init()
-{
- archive = archive_read_new();
archive_read_support_filter_all(archive);
+ archive_read_support_format_all(archive);
+ check(archive_read_open_filename(archive, path.c_str(), 16384), "failed to open archive: %s");
}
void TarArchive::close()
diff --git a/src/libutil/tarfile.hh b/src/libutil/tarfile.hh
index f107a7e2e..4d9141fd4 100644
--- a/src/libutil/tarfile.hh
+++ b/src/libutil/tarfile.hh
@@ -17,13 +17,10 @@ struct TarArchive {
// disable copy constructor
TarArchive(const TarArchive &) = delete;
- void init();
-
void close();
~TarArchive();
};
-
void unpackTarfile(Source & source, const Path & destDir);
void unpackTarfile(const Path & tarFile, const Path & destDir);
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index b833038a9..70eaf4f9c 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -406,8 +406,29 @@ static void _deletePath(int parentfd, const Path & path, uint64_t & bytesFreed)
throw SysError("getting status of '%1%'", path);
}
- if (!S_ISDIR(st.st_mode) && st.st_nlink == 1)
- bytesFreed += st.st_size;
+ if (!S_ISDIR(st.st_mode)) {
+ /* We are about to delete a file. Will it likely free space? */
+
+ switch (st.st_nlink) {
+ /* Yes: last link. */
+ case 1:
+ bytesFreed += st.st_size;
+ break;
+ /* Maybe: yes, if 'auto-optimise-store' or manual optimisation
+ was performed. Instead of checking for real let's assume
+ it's an optimised file and space will be freed.
+
+ In worst case we will double count on freed space for files
+ with exactly two hardlinks for unoptimised packages.
+ */
+ case 2:
+ bytesFreed += st.st_size;
+ break;
+ /* No: 3+ links. */
+ default:
+ break;
+ }
+ }
if (S_ISDIR(st.st_mode)) {
/* Make the directory accessible. */
@@ -682,7 +703,14 @@ std::string drainFD(int fd, bool block, const size_t reserveSize)
void drainFD(int fd, Sink & sink, bool block)
{
- int saved;
+ // silence GCC maybe-uninitialized warning in finally
+ int saved = 0;
+
+ if (!block) {
+ saved = fcntl(fd, F_GETFL);
+ if (fcntl(fd, F_SETFL, saved | O_NONBLOCK) == -1)
+ throw SysError("making file descriptor non-blocking");
+ }
Finally finally([&]() {
if (!block) {
@@ -691,12 +719,6 @@ void drainFD(int fd, Sink & sink, bool block)
}
});
- if (!block) {
- saved = fcntl(fd, F_GETFL);
- if (fcntl(fd, F_SETFL, saved | O_NONBLOCK) == -1)
- throw SysError("making file descriptor non-blocking");
- }
-
std::vector<unsigned char> buf(64 * 1024);
while (1) {
checkInterrupt();