aboutsummaryrefslogtreecommitdiff
path: root/src/libstore
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-03-27 23:40:35 +0100
committerEelco Dolstra <edolstra@gmail.com>2019-11-26 22:07:28 +0100
commit045708db4343174f30f3647776971c852f72a9e8 (patch)
treec37c82882d48e44338c9bae61eacb3839421f359 /src/libstore
parente60f6bd4ce831ced94fafeb527c429b6f88159ac (diff)
Make <nix/unpack-channel.nix> a builtin builder
This was the last function using a shell script, so this allows us to get rid of tar, coreutils, bash etc.
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/build.cc2
-rw-r--r--src/libstore/builtins.hh1
-rw-r--r--src/libstore/builtins/unpack-channel.cc39
-rw-r--r--src/libstore/local.mk2
-rw-r--r--src/libstore/rust.hh44
5 files changed, 87 insertions, 1 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 51a9fa35b..efbb7fc9f 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -3128,6 +3128,8 @@ void DerivationGoal::runChild()
builtinFetchurl(drv2, netrcData);
else if (drv->builder == "builtin:buildenv")
builtinBuildenv(drv2);
+ else if (drv->builder == "builtin:unpack-channel")
+ builtinUnpackChannel(drv2);
else
throw Error(format("unsupported builtin function '%1%'") % string(drv->builder, 8));
_exit(0);
diff --git a/src/libstore/builtins.hh b/src/libstore/builtins.hh
index 0d2da873e..87d6ce665 100644
--- a/src/libstore/builtins.hh
+++ b/src/libstore/builtins.hh
@@ -7,5 +7,6 @@ namespace nix {
// TODO: make pluggable.
void builtinFetchurl(const BasicDerivation & drv, const std::string & netrcData);
void builtinBuildenv(const BasicDerivation & drv);
+void builtinUnpackChannel(const BasicDerivation & drv);
}
diff --git a/src/libstore/builtins/unpack-channel.cc b/src/libstore/builtins/unpack-channel.cc
new file mode 100644
index 000000000..88202ec6b
--- /dev/null
+++ b/src/libstore/builtins/unpack-channel.cc
@@ -0,0 +1,39 @@
+#include "rust.hh"
+#include "builtins.hh"
+#include "compression.hh"
+
+namespace nix {
+
+void builtinUnpackChannel(const BasicDerivation & drv)
+{
+ auto getAttr = [&](const string & name) {
+ auto i = drv.env.find(name);
+ if (i == drv.env.end()) throw Error("attribute '%s' missing", name);
+ return i->second;
+ };
+
+ Path out = getAttr("out");
+ auto channelName = getAttr("channelName");
+ auto src = getAttr("src");
+
+ createDirs(out);
+
+ auto source = sinkToSource([&](Sink & sink) {
+ auto decompressor =
+ hasSuffix(src, ".bz2") ? makeDecompressionSink("bzip2", sink) :
+ hasSuffix(src, ".xz") ? makeDecompressionSink("xz", sink) :
+ makeDecompressionSink("none", sink);
+ readFile(src, *decompressor);
+ decompressor->finish();
+ });
+
+ unpack_tarfile(*source, out);
+
+ auto entries = readDirectory(out);
+ if (entries.size() != 1)
+ throw Error("channel tarball '%s' contains more than one file", src);
+ if (rename((out + "/" + entries[0].name).c_str(), (out + "/" + channelName).c_str()) == -1)
+ throw SysError("renaming channel directory");
+}
+
+}
diff --git a/src/libstore/local.mk b/src/libstore/local.mk
index d690fea28..d3254554d 100644
--- a/src/libstore/local.mk
+++ b/src/libstore/local.mk
@@ -6,7 +6,7 @@ libstore_DIR := $(d)
libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc)
-libstore_LIBS = libutil
+libstore_LIBS = libutil libnixrust
libstore_LDFLAGS = $(SQLITE3_LIBS) -lbz2 $(LIBCURL_LIBS) $(SODIUM_LIBS) -pthread
ifneq ($(OS), FreeBSD)
diff --git a/src/libstore/rust.hh b/src/libstore/rust.hh
new file mode 100644
index 000000000..7e6c2f54d
--- /dev/null
+++ b/src/libstore/rust.hh
@@ -0,0 +1,44 @@
+#include "serialise.hh"
+
+namespace rust {
+
+// Depending on the internal representation of Rust slices is slightly
+// evil...
+template<typename T> struct Slice
+{
+ T * ptr;
+ size_t size;
+
+ Slice(T * ptr, size_t size) : ptr(ptr), size(size)
+ {
+ assert(ptr);
+ }
+};
+
+struct StringSlice : Slice<char>
+{
+ StringSlice(const std::string & s): Slice((char *) s.data(), s.size()) {}
+};
+
+struct Source
+{
+ size_t (*fun)(void * source_this, rust::Slice<uint8_t> data);
+ nix::Source * _this;
+
+ Source(nix::Source & _this)
+ : fun(sourceWrapper), _this(&_this)
+ {}
+
+ // FIXME: how to propagate exceptions?
+ static size_t sourceWrapper(void * _this, rust::Slice<uint8_t> data)
+ {
+ auto n = ((nix::Source *) _this)->read(data.ptr, data.size);
+ return n;
+ }
+};
+
+}
+
+extern "C" {
+ bool unpack_tarfile(rust::Source source, rust::StringSlice dest_dir);
+}