aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/archive.hh
diff options
context:
space:
mode:
authorjade <lix@jade.fyi>2024-09-14 19:26:08 +0000
committerGerrit Code Review <gerrit@localhost>2024-09-14 19:26:08 +0000
commit8f88590d13363fef6b6a4576697afeccf835b081 (patch)
treed1330e0d01acbd6bc5b02be646788edc1120bdfd /src/libutil/archive.hh
parentb2fc007811a5afc473bf116fe8d38688b3699e25 (diff)
parentca1dc3f70bf98e2424b7b2666ee2180675b67451 (diff)
Merge changes Ia1481da4,Ifca1d74d into main
* changes: archive: refactor bad mutable-state API in the NAR parse listener archive: rename ParseSink to NARParseVisitor
Diffstat (limited to 'src/libutil/archive.hh')
-rw-r--r--src/libutil/archive.hh72
1 files changed, 37 insertions, 35 deletions
diff --git a/src/libutil/archive.hh b/src/libutil/archive.hh
index b34d06e3d..c633bee00 100644
--- a/src/libutil/archive.hh
+++ b/src/libutil/archive.hh
@@ -76,45 +76,47 @@ WireFormatGenerator dumpString(std::string_view s);
/**
* \todo Fix this API, it sucks.
+ * A visitor for NAR parsing that performs filesystem (or virtual-filesystem)
+ * actions to restore a NAR.
+ *
+ * Methods of this may arbitrarily fail due to filename collisions.
*/
-struct ParseSink
-{
- virtual void createDirectory(const Path & path) { };
-
- virtual void createRegularFile(const Path & path) { };
- virtual void closeRegularFile() { };
- virtual void isExecutable() { };
- virtual void preallocateContents(uint64_t size) { };
- virtual void receiveContents(std::string_view data) { };
-
- virtual void createSymlink(const Path & path, const std::string & target) { };
-};
-
-/**
- * If the NAR archive contains a single file at top-level, then save
- * the contents of the file to `s`. Otherwise barf.
- */
-struct RetrieveRegularNARSink : ParseSink
+struct NARParseVisitor
{
- bool regular = true;
- Sink & sink;
-
- RetrieveRegularNARSink(Sink & sink) : sink(sink) { }
-
- void createDirectory(const Path & path) override
+ /**
+ * A type-erased file handle specific to this particular NARParseVisitor.
+ */
+ struct FileHandle
{
- regular = false;
- }
-
- void receiveContents(std::string_view data) override
+ FileHandle() {}
+ FileHandle(FileHandle const &) = delete;
+ FileHandle & operator=(FileHandle &) = delete;
+
+ /** Puts one block of data into the file */
+ virtual void receiveContents(std::string_view data) { }
+
+ /**
+ * Explicitly closes the file. Further operations may throw an assert.
+ * This exists so that closing can fail and throw an exception without doing so in a destructor.
+ */
+ virtual void close() { }
+
+ virtual ~FileHandle() = default;
+ };
+
+ virtual void createDirectory(const Path & path) { }
+
+ /**
+ * Creates a regular file in the extraction output with the given size and executable flag.
+ * The size is guaranteed to be the true size of the file.
+ */
+ [[nodiscard]]
+ virtual std::unique_ptr<FileHandle> createRegularFile(const Path & path, uint64_t size, bool executable)
{
- sink(data);
+ return std::make_unique<FileHandle>();
}
- void createSymlink(const Path & path, const std::string & target) override
- {
- regular = false;
- }
+ virtual void createSymlink(const Path & path, const std::string & target) { }
};
namespace nar {
@@ -160,8 +162,8 @@ Generator<Entry> parse(Source & source);
}
-WireFormatGenerator parseAndCopyDump(ParseSink & sink, Source & source);
-void parseDump(ParseSink & sink, Source & source);
+WireFormatGenerator parseAndCopyDump(NARParseVisitor & sink, Source & source);
+void parseDump(NARParseVisitor & sink, Source & source);
void restorePath(const Path & path, Source & source);