From 045708db4343174f30f3647776971c852f72a9e8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 Mar 2019 23:40:35 +0100 Subject: Make a builtin builder This was the last function using a shell script, so this allows us to get rid of tar, coreutils, bash etc. --- src/libstore/build.cc | 2 ++ src/libstore/builtins.hh | 1 + src/libstore/builtins/unpack-channel.cc | 39 +++++++++++++++++++++++++++++ src/libstore/local.mk | 2 +- src/libstore/rust.hh | 44 +++++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 src/libstore/builtins/unpack-channel.cc create mode 100644 src/libstore/rust.hh (limited to 'src/libstore') 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 struct Slice +{ + T * ptr; + size_t size; + + Slice(T * ptr, size_t size) : ptr(ptr), size(size) + { + assert(ptr); + } +}; + +struct StringSlice : Slice +{ + StringSlice(const std::string & s): Slice((char *) s.data(), s.size()) {} +}; + +struct Source +{ + size_t (*fun)(void * source_this, rust::Slice 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 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); +} -- cgit v1.2.3