2017-04-26 15:04:45 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2011-10-10 18:12:40 +00:00
|
|
|
#include "EXTERN.h"
|
|
|
|
#include "perl.h"
|
|
|
|
#include "XSUB.h"
|
|
|
|
|
|
|
|
/* Prevent a clash between some Perl and libstdc++ macros. */
|
|
|
|
#undef do_open
|
|
|
|
#undef do_close
|
|
|
|
|
2024-11-12 23:07:17 +00:00
|
|
|
#include "lix/libstore/derivations.hh"
|
|
|
|
#include "lix/libstore/globals.hh"
|
|
|
|
#include "lix/libstore/store-api.hh"
|
|
|
|
#include "lix/libstore/crypto.hh"
|
2011-10-10 18:12:40 +00:00
|
|
|
|
2015-02-04 15:43:32 +00:00
|
|
|
#include <sodium.h>
|
2021-07-30 09:55:14 +00:00
|
|
|
#include <nlohmann/json.hpp>
|
2015-02-04 15:43:32 +00:00
|
|
|
|
2011-10-10 18:12:40 +00:00
|
|
|
|
|
|
|
using namespace nix;
|
|
|
|
|
|
|
|
|
2016-02-04 13:48:42 +00:00
|
|
|
static ref<Store> store()
|
2011-10-10 18:12:40 +00:00
|
|
|
{
|
2016-02-04 13:48:42 +00:00
|
|
|
static std::shared_ptr<Store> _store;
|
Eliminate the "store" global variable
Also, move a few free-standing functions into StoreAPI and Derivation.
Also, introduce a non-nullable smart pointer, ref<T>, which is just a
wrapper around std::shared_ptr ensuring that the pointer is never
null. (For reference-counted values, this is better than passing a
"T&", because the latter doesn't maintain the refcount. Usually, the
caller will have a shared_ptr keeping the value alive, but that's not
always the case, e.g., when passing a reference to a std::thread via
std::bind.)
2016-02-04 13:28:26 +00:00
|
|
|
if (!_store) {
|
2011-10-10 18:12:40 +00:00
|
|
|
try {
|
2023-01-28 10:48:23 +00:00
|
|
|
initLibStore();
|
Eliminate the "store" global variable
Also, move a few free-standing functions into StoreAPI and Derivation.
Also, introduce a non-nullable smart pointer, ref<T>, which is just a
wrapper around std::shared_ptr ensuring that the pointer is never
null. (For reference-counted values, this is better than passing a
"T&", because the latter doesn't maintain the refcount. Usually, the
caller will have a shared_ptr keeping the value alive, but that's not
always the case, e.g., when passing a reference to a std::thread via
std::bind.)
2016-02-04 13:28:26 +00:00
|
|
|
_store = openStore();
|
2011-10-10 18:12:40 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-10-10 18:12:40 +00:00
|
|
|
}
|
|
|
|
}
|
2016-02-04 13:48:42 +00:00
|
|
|
return ref<Store>(_store);
|
2011-10-10 18:12:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MODULE = Nix::Store PACKAGE = Nix::Store
|
|
|
|
PROTOTYPES: ENABLE
|
|
|
|
|
|
|
|
|
2014-01-21 15:38:03 +00:00
|
|
|
#undef dNOOP // Hack to work around "error: declaration of 'Perl___notused' has a different language linkage" error message on clang.
|
|
|
|
#define dNOOP
|
|
|
|
|
|
|
|
|
2011-10-10 18:12:40 +00:00
|
|
|
void init()
|
|
|
|
CODE:
|
Eliminate the "store" global variable
Also, move a few free-standing functions into StoreAPI and Derivation.
Also, introduce a non-nullable smart pointer, ref<T>, which is just a
wrapper around std::shared_ptr ensuring that the pointer is never
null. (For reference-counted values, this is better than passing a
"T&", because the latter doesn't maintain the refcount. Usually, the
caller will have a shared_ptr keeping the value alive, but that's not
always the case, e.g., when passing a reference to a std::thread via
std::bind.)
2016-02-04 13:28:26 +00:00
|
|
|
store();
|
2011-10-10 18:12:40 +00:00
|
|
|
|
|
|
|
|
2015-03-04 15:27:42 +00:00
|
|
|
void setVerbosity(int level)
|
|
|
|
CODE:
|
|
|
|
verbosity = (Verbosity) level;
|
|
|
|
|
|
|
|
|
2011-10-11 15:41:13 +00:00
|
|
|
int isValidPath(char * path)
|
2011-10-10 18:12:40 +00:00
|
|
|
CODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
RETVAL = store()->isValidPath(store()->parseStorePath(path));
|
2011-10-10 18:12:40 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-10-10 18:12:40 +00:00
|
|
|
}
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
|
|
|
|
|
2011-10-11 15:41:13 +00:00
|
|
|
SV * queryReferences(char * path)
|
2011-10-10 18:12:40 +00:00
|
|
|
PPCODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
for (auto & i : store()->queryPathInfo(store()->parseStorePath(path))->references)
|
|
|
|
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0)));
|
2011-10-10 18:12:40 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-10-10 18:12:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-11 15:41:13 +00:00
|
|
|
SV * queryPathHash(char * path)
|
2011-10-10 18:12:40 +00:00
|
|
|
PPCODE:
|
|
|
|
try {
|
2024-08-01 20:42:02 +00:00
|
|
|
auto s = store()->queryPathInfo(store()->parseStorePath(path))->narHash.to_string(Base::Base32, true);
|
2011-10-10 18:12:40 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-10-10 18:12:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-11 15:41:13 +00:00
|
|
|
SV * queryDeriver(char * path)
|
2011-10-10 18:12:40 +00:00
|
|
|
PPCODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
auto info = store()->queryPathInfo(store()->parseStorePath(path));
|
|
|
|
if (!info->deriver) XSRETURN_UNDEF;
|
|
|
|
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0)));
|
2011-10-10 18:12:40 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-10-10 18:12:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-17 20:55:45 +00:00
|
|
|
SV * queryPathInfo(char * path, int base32)
|
2011-10-10 18:12:40 +00:00
|
|
|
PPCODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
auto info = store()->queryPathInfo(store()->parseStorePath(path));
|
2020-03-10 10:00:17 +00:00
|
|
|
if (!info->deriver)
|
2011-10-10 18:12:40 +00:00
|
|
|
XPUSHs(&PL_sv_undef);
|
|
|
|
else
|
2019-12-05 18:11:09 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(*info->deriver).c_str(), 0)));
|
2024-08-01 20:42:02 +00:00
|
|
|
auto s = info->narHash.to_string(base32 ? Base::Base32 : Base::Base16, true);
|
2011-10-10 18:12:40 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
2016-04-19 16:50:15 +00:00
|
|
|
mXPUSHi(info->registrationTime);
|
|
|
|
mXPUSHi(info->narSize);
|
2020-11-21 22:06:15 +00:00
|
|
|
AV * refs = newAV();
|
2019-12-05 18:11:09 +00:00
|
|
|
for (auto & i : info->references)
|
2020-11-21 22:06:15 +00:00
|
|
|
av_push(refs, newSVpv(store()->printStorePath(i).c_str(), 0));
|
|
|
|
XPUSHs(sv_2mortal(newRV((SV *) refs)));
|
|
|
|
AV * sigs = newAV();
|
|
|
|
for (auto & i : info->sigs)
|
|
|
|
av_push(sigs, newSVpv(i.c_str(), 0));
|
|
|
|
XPUSHs(sv_2mortal(newRV((SV *) sigs)));
|
2011-10-10 18:12:40 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-10-10 18:12:40 +00:00
|
|
|
}
|
|
|
|
|
2021-07-30 09:55:14 +00:00
|
|
|
SV * queryRawRealisation(char * outputId)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
|
|
|
auto realisation = store()->queryRealisation(DrvOutput::parse(outputId));
|
|
|
|
if (realisation)
|
|
|
|
XPUSHs(sv_2mortal(newSVpv(realisation->toJSON().dump().c_str(), 0)));
|
|
|
|
else
|
|
|
|
XPUSHs(sv_2mortal(newSVpv("", 0)));
|
|
|
|
} catch (Error & e) {
|
|
|
|
croak("%s", e.what());
|
|
|
|
}
|
|
|
|
|
2011-10-10 18:12:40 +00:00
|
|
|
|
2012-07-17 22:55:39 +00:00
|
|
|
SV * queryPathFromHashPart(char * hashPart)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
auto path = store()->queryPathFromHashPart(hashPart);
|
|
|
|
XPUSHs(sv_2mortal(newSVpv(path ? store()->printStorePath(*path).c_str() : "", 0)));
|
2012-07-17 22:55:39 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2012-07-17 22:55:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-10 18:12:40 +00:00
|
|
|
SV * computeFSClosure(int flipDirection, int includeOutputs, ...)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
StorePathSet paths;
|
2011-10-10 18:12:40 +00:00
|
|
|
for (int n = 2; n < items; ++n)
|
2019-12-05 18:11:09 +00:00
|
|
|
store()->computeFSClosure(store()->parseStorePath(SvPV_nolen(ST(n))), paths, flipDirection, includeOutputs);
|
|
|
|
for (auto & i : paths)
|
|
|
|
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0)));
|
2011-10-10 18:12:40 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-10-10 18:12:40 +00:00
|
|
|
}
|
2011-10-11 15:41:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
SV * topoSortPaths(...)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
StorePathSet paths;
|
|
|
|
for (int n = 0; n < items; ++n) paths.insert(store()->parseStorePath(SvPV_nolen(ST(n))));
|
|
|
|
auto sorted = store()->topoSortPaths(paths);
|
|
|
|
for (auto & i : sorted)
|
|
|
|
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(i).c_str(), 0)));
|
2011-10-11 15:41:13 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-10-11 15:41:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SV * followLinksToStorePath(char * path)
|
|
|
|
CODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
RETVAL = newSVpv(store()->printStorePath(store()->followLinksToStorePath(path)).c_str(), 0);
|
2011-10-11 15:41:13 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-10-11 15:41:13 +00:00
|
|
|
}
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
2011-11-23 15:13:37 +00:00
|
|
|
|
|
|
|
|
2016-05-03 13:11:14 +00:00
|
|
|
void exportPaths(int fd, ...)
|
2011-11-23 15:13:37 +00:00
|
|
|
PPCODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
StorePathSet paths;
|
|
|
|
for (int n = 1; n < items; ++n) paths.insert(store()->parseStorePath(SvPV_nolen(ST(n))));
|
2011-11-23 15:13:37 +00:00
|
|
|
FdSink sink(fd);
|
2016-05-03 13:11:14 +00:00
|
|
|
store()->exportPaths(paths, sink);
|
2011-11-23 15:13:37 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-11-23 15:13:37 +00:00
|
|
|
}
|
2011-11-29 13:01:24 +00:00
|
|
|
|
|
|
|
|
2016-05-31 09:18:45 +00:00
|
|
|
void importPaths(int fd, int dontCheckSigs)
|
2014-07-11 14:02:19 +00:00
|
|
|
PPCODE:
|
|
|
|
try {
|
|
|
|
FdSource source(fd);
|
2020-07-13 15:37:44 +00:00
|
|
|
store()->importPaths(source, dontCheckSigs ? NoCheckSigs : CheckSigs);
|
2014-07-11 14:02:19 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2014-07-11 14:02:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-29 13:01:24 +00:00
|
|
|
SV * hashPath(char * algo, int base32, char * path)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
|
|
|
Hash h = hashPath(parseHashType(algo), path).first;
|
2024-08-01 20:42:02 +00:00
|
|
|
auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
|
2011-11-29 13:01:24 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-11-29 13:01:24 +00:00
|
|
|
}
|
2011-12-02 12:09:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
SV * hashFile(char * algo, int base32, char * path)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
|
|
|
Hash h = hashFile(parseHashType(algo), path);
|
2024-08-01 20:42:02 +00:00
|
|
|
auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
|
2011-12-02 12:09:24 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-12-02 12:09:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SV * hashString(char * algo, int base32, char * s)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
|
|
|
Hash h = hashString(parseHashType(algo), s);
|
2024-08-01 20:42:02 +00:00
|
|
|
auto s = h.to_string(base32 ? Base::Base32 : Base::Base16, false);
|
2011-12-02 12:09:24 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-12-02 12:09:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-03 13:33:17 +00:00
|
|
|
SV * convertHash(char * algo, char * s, int toBase32)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
2020-07-03 15:17:20 +00:00
|
|
|
auto h = Hash::parseAny(s, parseHashType(algo));
|
2024-08-01 20:42:02 +00:00
|
|
|
auto s = h.to_string(toBase32 ? Base::Base32 : Base::Base16, false);
|
2015-06-03 13:33:17 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2015-06-03 13:33:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-16 15:38:44 +00:00
|
|
|
SV * signString(char * secretKey_, char * msg)
|
2015-02-04 15:43:32 +00:00
|
|
|
PPCODE:
|
|
|
|
try {
|
2016-02-16 15:38:44 +00:00
|
|
|
auto sig = SecretKey(secretKey_).signDetached(msg);
|
|
|
|
XPUSHs(sv_2mortal(newSVpv(sig.c_str(), sig.size())));
|
2015-02-04 15:43:32 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2015-02-04 15:43:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int checkSignature(SV * publicKey_, SV * sig_, char * msg)
|
|
|
|
CODE:
|
|
|
|
try {
|
|
|
|
STRLEN publicKeyLen;
|
|
|
|
unsigned char * publicKey = (unsigned char *) SvPV(publicKey_, publicKeyLen);
|
|
|
|
if (publicKeyLen != crypto_sign_PUBLICKEYBYTES)
|
|
|
|
throw Error("public key is not valid");
|
|
|
|
|
|
|
|
STRLEN sigLen;
|
|
|
|
unsigned char * sig = (unsigned char *) SvPV(sig_, sigLen);
|
|
|
|
if (sigLen != crypto_sign_BYTES)
|
|
|
|
throw Error("signature is not valid");
|
|
|
|
|
|
|
|
RETVAL = crypto_sign_verify_detached(sig, (unsigned char *) msg, strlen(msg), publicKey) == 0;
|
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2015-02-04 15:43:32 +00:00
|
|
|
}
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
|
|
|
|
|
|
|
|
2011-12-02 12:09:24 +00:00
|
|
|
SV * addToStore(char * srcPath, int recursive, char * algo)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
2020-03-30 22:40:41 +00:00
|
|
|
auto method = recursive ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat;
|
|
|
|
auto path = store()->addToStore(std::string(baseNameOf(srcPath)), srcPath, method, parseHashType(algo));
|
2019-12-05 18:11:09 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(path).c_str(), 0)));
|
2011-12-02 12:09:24 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-12-02 12:09:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
2020-07-03 14:49:22 +00:00
|
|
|
auto h = Hash::parseAny(hash, parseHashType(algo));
|
2020-03-30 22:40:41 +00:00
|
|
|
auto method = recursive ? FileIngestionMethod::Recursive : FileIngestionMethod::Flat;
|
2020-10-07 13:52:20 +00:00
|
|
|
auto path = store()->makeFixedOutputPath(name, FixedOutputInfo {
|
2023-07-05 22:53:44 +00:00
|
|
|
.method = method,
|
|
|
|
.hash = h,
|
2023-02-28 16:57:20 +00:00
|
|
|
.references = {},
|
2020-10-07 13:52:20 +00:00
|
|
|
});
|
2019-12-05 18:11:09 +00:00
|
|
|
XPUSHs(sv_2mortal(newSVpv(store()->printStorePath(path).c_str(), 0)));
|
2011-12-02 12:09:24 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2011-12-02 12:09:24 +00:00
|
|
|
}
|
2012-03-19 03:14:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
SV * derivationFromPath(char * drvPath)
|
|
|
|
PREINIT:
|
|
|
|
HV *hash;
|
|
|
|
CODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
Derivation drv = store()->derivationFromPath(store()->parseStorePath(drvPath));
|
2012-03-19 03:14:21 +00:00
|
|
|
hash = newHV();
|
2013-03-08 00:24:59 +00:00
|
|
|
|
|
|
|
HV * outputs = newHV();
|
2020-08-14 17:00:13 +00:00
|
|
|
for (auto & i : drv.outputsAndOptPaths(*store())) {
|
2020-07-12 18:26:10 +00:00
|
|
|
hv_store(
|
|
|
|
outputs, i.first.c_str(), i.first.size(),
|
2020-08-14 17:00:13 +00:00
|
|
|
!i.second.second
|
2020-08-08 15:48:51 +00:00
|
|
|
? newSV(0) /* null value */
|
2020-08-14 17:00:13 +00:00
|
|
|
: newSVpv(store()->printStorePath(*i.second.second).c_str(), 0),
|
2020-07-12 18:26:10 +00:00
|
|
|
0);
|
2020-08-08 15:48:51 +00:00
|
|
|
}
|
2013-03-08 00:24:59 +00:00
|
|
|
hv_stores(hash, "outputs", newRV((SV *) outputs));
|
|
|
|
|
2012-03-19 03:14:21 +00:00
|
|
|
AV * inputDrvs = newAV();
|
Allow dynamic derivation deps in `inputDrvs`
We use the same nested map representation we used for goals, again in
order to save space. We might someday want to combine with `inputDrvs`,
by doing `V = bool` instead of `V = std::set<OutputName>`, but we are
not doing that yet for sake of a smaller diff.
The ATerm format for Derivations also needs to be extended, in addition
to the in-memory format. To accomodate this, we added a new basic
versioning scheme, so old versions of Nix will get nice errors. (And
going forward, if the ATerm format changes again the errors will be even
better.)
`parsedStrings`, an internal function used as part of parsing
derivations in A-Term format, used to consume the final `]` but expect
the initial `[` to already be consumed. This made for what looked like
unbalanced brackets at callsites, which was confusing. Now it consumes
both which is hopefully less confusing.
As part of testing, we also created a unit test for the A-Term format for
regular non-experimental derivations too.
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
Apply suggestions from code review
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
2021-10-01 22:05:53 +00:00
|
|
|
for (auto & i : drv.inputDrvs.map)
|
2019-12-05 18:11:09 +00:00
|
|
|
av_push(inputDrvs, newSVpv(store()->printStorePath(i.first).c_str(), 0)); // !!! ignores i->second
|
2012-03-19 03:14:21 +00:00
|
|
|
hv_stores(hash, "inputDrvs", newRV((SV *) inputDrvs));
|
2013-03-08 00:24:59 +00:00
|
|
|
|
2012-03-19 03:14:21 +00:00
|
|
|
AV * inputSrcs = newAV();
|
2019-12-05 18:11:09 +00:00
|
|
|
for (auto & i : drv.inputSrcs)
|
|
|
|
av_push(inputSrcs, newSVpv(store()->printStorePath(i).c_str(), 0));
|
2012-03-19 03:14:21 +00:00
|
|
|
hv_stores(hash, "inputSrcs", newRV((SV *) inputSrcs));
|
2013-03-08 00:24:59 +00:00
|
|
|
|
2012-03-19 03:14:21 +00:00
|
|
|
hv_stores(hash, "platform", newSVpv(drv.platform.c_str(), 0));
|
|
|
|
hv_stores(hash, "builder", newSVpv(drv.builder.c_str(), 0));
|
2013-03-08 00:24:59 +00:00
|
|
|
|
2012-03-19 03:14:21 +00:00
|
|
|
AV * args = newAV();
|
2019-12-05 18:11:09 +00:00
|
|
|
for (auto & i : drv.args)
|
|
|
|
av_push(args, newSVpv(i.c_str(), 0));
|
2012-03-19 03:14:21 +00:00
|
|
|
hv_stores(hash, "args", newRV((SV *) args));
|
2013-03-08 00:24:59 +00:00
|
|
|
|
2012-03-19 03:14:21 +00:00
|
|
|
HV * env = newHV();
|
2019-12-05 18:11:09 +00:00
|
|
|
for (auto & i : drv.env)
|
|
|
|
hv_store(env, i.first.c_str(), i.first.size(), newSVpv(i.second.c_str(), 0), 0);
|
2012-03-19 03:14:21 +00:00
|
|
|
hv_stores(hash, "env", newRV((SV *) env));
|
2013-03-08 00:24:59 +00:00
|
|
|
|
2012-03-19 03:14:21 +00:00
|
|
|
RETVAL = newRV_noinc((SV *)hash);
|
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2012-03-19 03:14:21 +00:00
|
|
|
}
|
|
|
|
OUTPUT:
|
|
|
|
RETVAL
|
2015-10-09 10:49:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
void addTempRoot(char * storePath)
|
|
|
|
PPCODE:
|
|
|
|
try {
|
2019-12-05 18:11:09 +00:00
|
|
|
store()->addTempRoot(store()->parseStorePath(storePath));
|
2015-10-09 10:49:47 +00:00
|
|
|
} catch (Error & e) {
|
2016-01-07 13:33:13 +00:00
|
|
|
croak("%s", e.what());
|
2015-10-09 10:49:47 +00:00
|
|
|
}
|
2020-09-17 08:42:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
SV * getBinDir()
|
|
|
|
PPCODE:
|
|
|
|
XPUSHs(sv_2mortal(newSVpv(settings.nixBinDir.c_str(), 0)));
|
|
|
|
|
|
|
|
|
|
|
|
SV * getStoreDir()
|
|
|
|
PPCODE:
|
|
|
|
XPUSHs(sv_2mortal(newSVpv(settings.nixStore.c_str(), 0)));
|