git.delta.rocks / fleet / refs/commits / 615754ca0747

difftreelog

source

crates/nix-eval/src/lib.cc8.7 KiBsourcehistory
1#include "nix-eval/src/lib.rs"2#include "lib.hh"3#include <nix/fetchers/fetch-settings.hh>4#include <nix/store/build-result.hh>5#include <nix/store/content-address.hh>6#include <nix/store/derived-path.hh>7#include <nix/store/local-fs-store.hh>8#include <nix/store/outputs-spec.hh>9#include <nix/store/path-info.hh>10#include <nix/store/profiles.hh>11#include <nix/store/realisation.hh>12#include <nix/store/store-api.hh>13#include <nix/util/file-system.hh>14#include <nix/util/hash.hh>15#include <nix/util/posix-source-accessor.hh>16#include <nix/util/ref.hh>17#include <nix/util/serialise.hh>18#include <nix/util/signature/local-keys.hh>19#include <nix/util/signature/signer.hh>20#include <nix/util/source-path.hh>21#include <nix_api_fetchers.h>22#include <nix_api_store_internal.h>23#include <sstream>2425struct nix_fetchers_settings {26  nix::ref<nix::fetchers::Settings> settings;27};2829extern "C" {30void set_fetcher_setting(nix_fetchers_settings *settings_struct,31                         const char *setting, const char *value) {32  auto &settings_ref = settings_struct->settings;33  bool result = settings_ref->set(setting, value);34}35}3637rust::String switch_profile(Store *store, rust::Str profile,38                            rust::Str store_path) {39  try {40    auto nixStore = store->ptr;41    auto *lfs = dynamic_cast<nix::LocalFSStore *>(&*nixStore);42    if (!lfs)43      return rust::String("destination is not a local-fs store");44    auto path = nixStore->parseStorePath(std::string(store_path));45    std::filesystem::path prof = std::string(profile);46    auto gen = nix::createGeneration(*lfs, prof, path);47    nix::switchLink(prof, gen);48    return rust::String();49  } catch (const std::exception &e) {50    return rust::String(e.what());51  }52}5354rust::String sign_closure(Store *store, rust::Str store_path,55                          rust::Str key_file) {56  try {57    auto nixStore = store->ptr;58    nix::LocalSigner signer(59        nix::SecretKey::parse(nix::readFile(std::string(key_file))));60    auto root = nixStore->parseStorePath(std::string(store_path));61    nix::StorePathSet closure;62    nixStore->computeFSClosure(root, closure);63    for (auto &p : closure) {64      auto info = nixStore->queryPathInfo(p);65      nix::ValidPathInfo info2(*info);66      info2.sign(*nixStore, signer);67      nixStore->addSignatures(p, info2.sigs);68    }69    return rust::String();70  } catch (const std::exception &e) {71    return rust::String(e.what());72  }73}7475CxxListGenerationsResult list_generations(rust::Str profile_path) {76  CxxListGenerationsResult out{rust::String(), {}};77  try {78    auto [gens, current] =79        nix::findGenerations(std::filesystem::path(std::string(profile_path)));80    for (auto &g : gens) {81      CxxProfileGeneration cg{};82      cg.id = g.number;83      cg.store_path = rust::String(g.path.string());84      cg.creation_time_unix = static_cast<int64_t>(g.creationTime);85      cg.current = current.has_value() && *current == g.number;86      out.generations.push_back(cg);87    }88  } catch (const std::exception &e) {89    out.error = rust::String(e.what());90  }91  return out;92}9394static std::vector<std::string> split_lines(rust::Str joined) {95  std::vector<std::string> out;96  std::string buf;97  std::istringstream iss((std::string(joined)));98  while (std::getline(iss, buf)) {99    if (!buf.empty())100      out.push_back(buf);101  }102  return out;103}104105CxxBuildResult build_drv_outputs(Store *store, rust::Str drv_path,106                                 // TODO: Vec<str>107                                 rust::Str output_names_joined) {108  CxxBuildResult res{rust::String(), {}};109  try {110    auto nixStore = store->ptr;111    auto sp = nixStore->parseStorePath(std::string(drv_path));112113    nix::DerivedPath::Built built{114        .drvPath = nix::makeConstantStorePathRef(sp),115        .outputs = nix::OutputsSpec{nix::OutputsSpec::All{}},116    };117    auto names = split_lines(output_names_joined);118    if (!names.empty()) {119      std::set<nix::OutputName, std::less<>> nameSet;120      for (auto &n : names)121        nameSet.insert(n);122      built.outputs =123          nix::OutputsSpec{nix::OutputsSpec::Names{std::move(nameSet)}};124    }125126    std::vector<nix::DerivedPath> reqs;127    reqs.push_back(built);128129    auto results = nixStore->buildPathsWithResults(reqs);130    for (auto &r : results) {131      if (auto *failure = r.tryGetFailure()) {132        res.error = rust::String(failure->what());133        return res;134      }135    }136    for (auto &r : results) {137      if (auto *success = r.tryGetSuccess()) {138        for (auto &[name, real] : success->builtOutputs) {139          res.outputs.push_back(140              rust::String(nixStore->printStorePath(real.outPath)));141        }142      }143    }144  } catch (const std::exception &e) {145    res.error = rust::String(e.what());146  }147  return res;148}149150CxxBuildResult substitute_paths(Store *store, rust::Str paths_joined) {151  CxxBuildResult res{rust::String(), {}};152  try {153    auto nixStore = store->ptr;154    auto paths = split_lines(paths_joined);155156    std::vector<nix::DerivedPath> reqs;157    reqs.reserve(paths.size());158    for (auto &p : paths) {159      reqs.push_back(nix::DerivedPath::Opaque{nixStore->parseStorePath(p)});160    }161162    // Substituter miss will cause scheduler to trigger build163    auto results = nixStore->buildPathsWithResults(reqs);164    for (auto &r : results) {165      if (r.tryGetSuccess() == nullptr)166        continue;167      if (auto *opaque = std::get_if<nix::DerivedPath::Opaque>(&r.path.raw())) {168        res.outputs.push_back(169            rust::String(nixStore->printStorePath(opaque->path)));170      }171    }172  } catch (const std::exception &e) {173    res.error = rust::String(e.what());174  }175  return res;176}177178bool is_valid_path(Store *store, rust::Str path) {179  try {180    auto nixStore = store->ptr;181    auto sp = nixStore->parseStorePath(std::string(path));182    return nixStore->isValidPath(sp);183  } catch (const std::exception &) {184    return false;185  }186}187188CxxPathInfo query_path_info(Store *store, rust::Str path) {189  CxxPathInfo out{rust::String(), rust::String(), 0, {}, {}};190  try {191    auto nixStore = store->ptr;192    auto sp = nixStore->parseStorePath(std::string(path));193    auto info = nixStore->queryPathInfo(sp);194    out.nar_hash =195        rust::String(info->narHash.to_string(nix::HashFormat::Nix32, true));196    out.nar_size = info->narSize;197    for (auto &r : info->references)198      out.references.push_back(rust::String(nixStore->printStorePath(r)));199    for (auto &s : info->sigs)200      out.sigs.push_back(rust::String(s.to_string()));201  } catch (const std::exception &e) {202    out.error = rust::String(e.what());203  }204  return out;205}206207CxxBuildResult compute_closure(Store *store, rust::Str path) {208  CxxBuildResult res{rust::String(), {}};209  try {210    auto nixStore = store->ptr;211    auto root = nixStore->parseStorePath(std::string(path));212    nix::StorePathSet closure;213    nixStore->computeFSClosure(root, closure);214    for (auto &p : closure)215      res.outputs.push_back(rust::String(nixStore->printStorePath(p)));216  } catch (const std::exception &e) {217    res.error = rust::String(e.what());218  }219  return res;220}221222namespace {223struct RustFnSink : nix::Sink {224  size_t data;225  rust::Fn<bool(size_t, rust::Slice<const uint8_t>)> sink;226  RustFnSink(size_t data,227             rust::Fn<bool(size_t, rust::Slice<const uint8_t>)> sink)228      : data(data), sink(sink) {}229  void operator()(std::string_view chunk) override {230    bool ok = sink(data, rust::Slice<const uint8_t>(231                             reinterpret_cast<const uint8_t *>(chunk.data()),232                             chunk.size()));233    if (!ok)234      throw nix::Error("nar sink aborted");235  }236};237} // namespace238239rust::String nar_from_path(Store *store, rust::Str path, size_t sink_data,240                           rust::Fn<bool(size_t, rust::Slice<const uint8_t>)> sink) {241  try {242    auto nixStore = store->ptr;243    auto sp = nixStore->parseStorePath(std::string(path));244    RustFnSink s(sink_data, sink);245    nixStore->narFromPath(sp, s);246    return rust::String();247  } catch (const std::exception &e) {248    return rust::String(e.what());249  }250}251252AddFileToStoreResult add_file_to_store(Store *store, rust::Str name,253                                       rust::Str path) {254  AddFileToStoreResult out{rust::String(), rust::String(), rust::String()};255  try {256    auto nixStore = store->ptr;257    auto src = nix::PosixSourceAccessor::createAtRoot(258        std::filesystem::path(std::string(path)));259    auto info = nixStore->addToStoreSlow(std::string(name), src,260                                         nix::ContentAddressMethod::Raw::Flat,261                                         nix::HashAlgorithm::SHA256);262    out.store_path = rust::String(nixStore->printStorePath(info.path));263    if (info.ca.has_value()) {264      out.hash =265          rust::String(info.ca->hash.to_string(nix::HashFormat::SRI, true));266    }267  } catch (const std::exception &e) {268    out.error = rust::String(e.what());269  }270  return out;271}