From 045708db4343174f30f3647776971c852f72a9e8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 27 Mar 2019 23:40:35 +0100 Subject: [PATCH] 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. --- corepkgs/config.nix.in | 10 +----- corepkgs/unpack-channel.nix | 35 +++------------------ nix-rust/src/lib.rs | 5 ++- src/libstore/build.cc | 2 ++ src/libstore/builtins.hh | 1 + src/libstore/builtins/unpack-channel.cc | 39 +++++++++++++++++++++++ src/libstore/local.mk | 2 +- src/{nix/test.cc => libstore/rust.hh} | 41 +------------------------ src/nix/local.mk | 4 +-- 9 files changed, 55 insertions(+), 84 deletions(-) create mode 100644 src/libstore/builtins/unpack-channel.cc rename src/{nix/test.cc => libstore/rust.hh} (53%) diff --git a/corepkgs/config.nix.in b/corepkgs/config.nix.in index 32ce6b399..4ea182d8f 100644 --- a/corepkgs/config.nix.in +++ b/corepkgs/config.nix.in @@ -1,3 +1,4 @@ +# FIXME: remove this file? let fromEnv = var: def: let val = builtins.getEnv var; in @@ -17,13 +18,4 @@ in rec { nixLocalstateDir = "@localstatedir@"; nixSysconfDir = "@sysconfdir@"; nixStoreDir = fromEnv "NIX_STORE_DIR" "@storedir@"; - - # If Nix is installed in the Nix store, then automatically add it as - # a dependency to the core packages. This ensures that they work - # properly in a chroot. - chrootDeps = - if dirOf nixPrefix == builtins.storeDir then - [ (builtins.storePath nixPrefix) ] - else - [ ]; } diff --git a/corepkgs/unpack-channel.nix b/corepkgs/unpack-channel.nix index d39a20637..10515bc8b 100644 --- a/corepkgs/unpack-channel.nix +++ b/corepkgs/unpack-channel.nix @@ -1,39 +1,12 @@ -with import ; - -let - - builder = builtins.toFile "unpack-channel.sh" - '' - mkdir $out - cd $out - xzpat="\.xz\$" - gzpat="\.gz\$" - if [[ "$src" =~ $xzpat ]]; then - ${xz} -d < $src | ${tar} xf - ${tarFlags} - elif [[ "$src" =~ $gzpat ]]; then - ${gzip} -d < $src | ${tar} xf - ${tarFlags} - else - ${bzip2} -d < $src | ${tar} xf - ${tarFlags} - fi - if [ * != $channelName ]; then - mv * $out/$channelName - fi - ''; - -in - { name, channelName, src }: derivation { - system = builtins.currentSystem; - builder = shell; - args = [ "-e" builder ]; - inherit name channelName src; + builder = "builtin:unpack-channel"; - PATH = "${nixBinDir}:${coreutils}"; + system = "builtin"; + + inherit name channelName src; # No point in doing this remotely. preferLocalBuild = true; - - inherit chrootDeps; } diff --git a/nix-rust/src/lib.rs b/nix-rust/src/lib.rs index 799d52e31..ac6dee543 100644 --- a/nix-rust/src/lib.rs +++ b/nix-rust/src/lib.rs @@ -33,7 +33,7 @@ pub extern "C" fn unpack_tarfile(source: Source, dest_dir: &str) -> bool { for file in tar.entries().unwrap() { let mut file = file.unwrap(); - let dest_file = dest_dir.join(file.header().path().unwrap()); + let dest_file = dest_dir.join(file.path().unwrap()); fs::create_dir_all(dest_file.parent().unwrap()).unwrap(); @@ -55,6 +55,9 @@ pub extern "C" fn unpack_tarfile(source: Source, dest_dir: &str) -> bool { .unwrap(); io::copy(&mut file, &mut f).unwrap(); } + tar::EntryType::Symlink => { + std::os::unix::fs::symlink(file.header().link_name().unwrap().unwrap(), dest_file).unwrap(); + } t => panic!("Unsupported tar entry type '{:?}'.", t), } } 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/nix/test.cc b/src/libstore/rust.hh similarity index 53% rename from src/nix/test.cc rename to src/libstore/rust.hh index 7f1f0d47a..7e6c2f54d 100644 --- a/src/nix/test.cc +++ b/src/libstore/rust.hh @@ -1,9 +1,4 @@ -#include "command.hh" -#include "store-api.hh" -#include "common-args.hh" -#include "compression.hh" - -using namespace nix; +#include "serialise.hh" namespace rust { @@ -47,37 +42,3 @@ struct Source extern "C" { bool unpack_tarfile(rust::Source source, rust::StringSlice dest_dir); } - -struct CmdTest : StoreCommand -{ - CmdTest() - { - } - - std::string name() override - { - return "test"; - } - - std::string description() override - { - return "bla bla"; - } - - void run(ref store) override - { - auto source = sinkToSource([&](Sink & sink) { - auto decompressor = makeDecompressionSink("bzip2", sink); - readFile("./nix-2.2.tar.bz2", *decompressor); - decompressor->finish(); - }); - - std::string destDir = "./dest"; - - deletePath(destDir); - - unpack_tarfile(*source, destDir); - } -}; - -static RegisterCommand r(make_ref()); diff --git a/src/nix/local.mk b/src/nix/local.mk index a145cf9b1..c09efd1fc 100644 --- a/src/nix/local.mk +++ b/src/nix/local.mk @@ -15,9 +15,9 @@ nix_SOURCES := \ $(wildcard src/nix-prefetch-url/*.cc) \ $(wildcard src/nix-store/*.cc) \ -nix_LIBS = libexpr libmain libstore libutil libnixrust +nix_LIBS = libexpr libmain libstore libutil -nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -lboost_context -lboost_thread -lboost_system -Lnix-rust/target/release +nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -lboost_context -lboost_thread -lboost_system $(foreach name, \ nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \