1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-29 14:53:16 +02:00

Merge remote-tracking branch 'origin/master' into lazy-trees

This commit is contained in:
Eelco Dolstra 2022-10-26 16:30:23 +02:00
commit e2353b9b45
33 changed files with 196 additions and 55 deletions

View file

@ -19,9 +19,9 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: cachix/install-nix-action@v17 - uses: cachix/install-nix-action@v18
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/cachix-action@v10 - uses: cachix/cachix-action@v11
if: needs.check_secrets.outputs.cachix == 'true' if: needs.check_secrets.outputs.cachix == 'true'
with: with:
name: '${{ env.CACHIX_NAME }}' name: '${{ env.CACHIX_NAME }}'
@ -58,8 +58,8 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/install-nix-action@v17 - uses: cachix/install-nix-action@v18
- uses: cachix/cachix-action@v10 - uses: cachix/cachix-action@v11
with: with:
name: '${{ env.CACHIX_NAME }}' name: '${{ env.CACHIX_NAME }}'
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
@ -77,7 +77,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/install-nix-action@v17 - uses: cachix/install-nix-action@v18
with: with:
install_url: '${{needs.installer.outputs.installerURL}}' install_url: '${{needs.installer.outputs.installerURL}}'
install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve" install_options: "--tarball-url-prefix https://${{ env.CACHIX_NAME }}.cachix.org/serve"
@ -102,10 +102,10 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: cachix/install-nix-action@v17 - uses: cachix/install-nix-action@v18
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV - run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#default.version | tr -d \")" >> $GITHUB_ENV - run: echo NIX_VERSION="$(nix --experimental-features 'nix-command flakes' eval .\#default.version | tr -d \")" >> $GITHUB_ENV
- uses: cachix/cachix-action@v10 - uses: cachix/cachix-action@v11
if: needs.check_secrets.outputs.cachix == 'true' if: needs.check_secrets.outputs.cachix == 'true'
with: with:
name: '${{ env.CACHIX_NAME }}' name: '${{ env.CACHIX_NAME }}'

View file

@ -1,11 +1,11 @@
{ command }: { toplevel }:
with builtins; with builtins;
with import <nix/utils.nix>; with import <nix/utils.nix>;
let let
showCommand = { command, details, filename }: showCommand = { command, details, filename, toplevel }:
let let
result = '' result = ''
> **Warning** \ > **Warning** \
@ -57,14 +57,15 @@ let
maybeOptions = if details.flags == {} then "" else '' maybeOptions = if details.flags == {} then "" else ''
# Options # Options
${showOptions details.flags} ${showOptions details.flags toplevel.flags}
''; '';
showOptions = options: showOptions = options: commonOptions:
let let
allOptions = options // commonOptions;
showCategory = cat: '' showCategory = cat: ''
${if cat != "" then "**${cat}:**" else ""} ${if cat != "" then "**${cat}:**" else ""}
${listOptions (filterAttrs (n: v: v.category == cat) options)} ${listOptions (filterAttrs (n: v: v.category == cat) allOptions)}
''; '';
listOptions = opts: concatStringsSep "\n" (attrValues (mapAttrs showOption opts)); listOptions = opts: concatStringsSep "\n" (attrValues (mapAttrs showOption opts));
showOption = name: option: showOption = name: option:
@ -76,30 +77,33 @@ let
${option.description} ${option.description}
''; '';
categories = sort builtins.lessThan (unique (map (cmd: cmd.category) (attrValues options))); categories = sort builtins.lessThan (unique (map (cmd: cmd.category) (attrValues allOptions)));
in concatStrings (map showCategory categories); in concatStrings (map showCategory categories);
in squash result; in squash result;
appendName = filename: name: (if filename == "nix" then "nix3" else filename) + "-" + name; appendName = filename: name: (if filename == "nix" then "nix3" else filename) + "-" + name;
processCommand = { command, details, filename }: processCommand = { command, details, filename, toplevel }:
let let
cmd = { cmd = {
inherit command; inherit command;
name = filename + ".md"; name = filename + ".md";
value = showCommand { inherit command details filename; }; value = showCommand { inherit command details filename toplevel; };
}; };
subcommand = subCmd: processCommand { subcommand = subCmd: processCommand {
command = command + " " + subCmd; command = command + " " + subCmd;
details = details.commands.${subCmd}; details = details.commands.${subCmd};
filename = appendName filename subCmd; filename = appendName filename subCmd;
inherit toplevel;
}; };
in [ cmd ] ++ concatMap subcommand (attrNames details.commands or {}); in [ cmd ] ++ concatMap subcommand (attrNames details.commands or {});
parsedToplevel = builtins.fromJSON toplevel;
manpages = processCommand { manpages = processCommand {
command = "nix"; command = "nix";
details = builtins.fromJSON command; details = parsedToplevel;
filename = "nix"; filename = "nix";
toplevel = parsedToplevel;
}; };
tableOfContents = let tableOfContents = let

View file

@ -11,16 +11,16 @@ concatStrings (map
+ concatStrings (map (s: " ${s}\n") (splitLines option.description)) + "\n\n" + concatStrings (map (s: " ${s}\n") (splitLines option.description)) + "\n\n"
+ (if option.documentDefault + (if option.documentDefault
then " **Default:** " + ( then " **Default:** " + (
if option.value == "" || option.value == [] if option.defaultValue == "" || option.defaultValue == []
then "*empty*" then "*empty*"
else if isBool option.value else if isBool option.defaultValue
then (if option.value then "`true`" else "`false`") then (if option.defaultValue then "`true`" else "`false`")
else else
# n.b. a StringMap value type is specified as a string, but # n.b. a StringMap value type is specified as a string, but
# this shows the value type. The empty stringmap is "null" in # this shows the value type. The empty stringmap is "null" in
# JSON, but that converts to "{ }" here. # JSON, but that converts to "{ }" here.
(if isAttrs option.value then "`\"\"`" (if isAttrs option.defaultValue then "`\"\"`"
else "`" + toString option.value + "`")) + "\n\n" else "`" + toString option.defaultValue + "`")) + "\n\n"
else " **Default:** *machine-specific*\n") else " **Default:** *machine-specific*\n")
+ (if option.aliases != [] + (if option.aliases != []
then " **Deprecated alias:** " + (concatStringsSep ", " (map (s: "`${s}`") option.aliases)) + "\n\n" then " **Deprecated alias:** " + (concatStringsSep ", " (map (s: "`${s}`") option.aliases)) + "\n\n"

View file

@ -50,7 +50,7 @@ $(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/command-ref/new-cli
$(d)/src/command-ref/new-cli: $(d)/nix.json $(d)/generate-manpage.nix $(bindir)/nix $(d)/src/command-ref/new-cli: $(d)/nix.json $(d)/generate-manpage.nix $(bindir)/nix
@rm -rf $@ @rm -rf $@
$(trace-gen) $(nix-eval) --write-to $@ --expr 'import doc/manual/generate-manpage.nix { command = builtins.readFile $<; }' $(trace-gen) $(nix-eval) --write-to $@ --expr 'import doc/manual/generate-manpage.nix { toplevel = builtins.readFile $<; }'
$(d)/src/command-ref/conf-file.md: $(d)/conf-file.json $(d)/generate-options.nix $(d)/src/command-ref/conf-file-prefix.md $(bindir)/nix $(d)/src/command-ref/conf-file.md: $(d)/conf-file.json $(d)/generate-options.nix $(d)/src/command-ref/conf-file-prefix.md $(bindir)/nix
@cat doc/manual/src/command-ref/conf-file-prefix.md > $@.tmp @cat doc/manual/src/command-ref/conf-file-prefix.md > $@.tmp

View file

@ -150,6 +150,20 @@
recognized as a path. `a.${foo}/b.${bar}` is a syntactically valid division recognized as a path. `a.${foo}/b.${bar}` is a syntactically valid division
operation. `./a.${foo}/b.${bar}` is a path. operation. `./a.${foo}/b.${bar}` is a path.
When a path appears in an antiquotation, and is thus coerced into a string,
the path is first copied into the Nix store and the resulting string is
the Nix store path. For instance `"${./foo.txt}" will cause `foo.txt` in
the current directory to be copied into the Nix store and result in the
string `"/nix/store/<HASH>-foo.txt"`.
Note that the Nix language assumes that all input files will remain
_unchanged_ during the course of the Nix expression evaluation.
If you for example antiquote a file path during a `nix repl` session, and
then later in the same session, after having changed the file contents,
evaluate the antiquotation with the file path again, then Nix will still
return the first store path. It will _not_ reread the file contents to
produce a different Nix store path.
- <a id="type-boolean" href="#type-boolean">Boolean</a> - <a id="type-boolean" href="#type-boolean">Boolean</a>
*Booleans* with values `true` and `false`. *Booleans* with values `true` and `false`.

View file

@ -28,7 +28,9 @@ if test -n "$HOME" && test -n "$USER"
# Only use MANPATH if it is already set. In general `man` will just simply # Only use MANPATH if it is already set. In general `man` will just simply
# pick up `.nix-profile/share/man` because is it close to `.nix-profile/bin` # pick up `.nix-profile/share/man` because is it close to `.nix-profile/bin`
# which is in the $PATH. For more info, run `manpath -d`. # which is in the $PATH. For more info, run `manpath -d`.
set --export --prepend --path MANPATH "$NIX_LINK/share/man" if set --query MANPATH
set --export --prepend --path MANPATH "$NIX_LINK/share/man"
end
fish_add_path --prepend --global "$NIX_LINK/bin" fish_add_path --prepend --global "$NIX_LINK/bin"
set --erase NIX_LINK set --erase NIX_LINK

View file

@ -88,7 +88,8 @@ EvalCommand::EvalCommand()
{ {
addFlag({ addFlag({
.longName = "debugger", .longName = "debugger",
.description = "start an interactive environment if evaluation fails", .description = "Start an interactive environment if evaluation fails.",
.category = MixEvalArgs::category,
.handler = {&startReplOnEvalErrors, true}, .handler = {&startReplOnEvalErrors, true},
}); });
} }
@ -228,7 +229,7 @@ MixProfile::MixProfile()
{ {
addFlag({ addFlag({
.longName = "profile", .longName = "profile",
.description = "The profile to update.", .description = "The profile to operate on.",
.labels = {"path"}, .labels = {"path"},
.handler = {&profile}, .handler = {&profile},
.completer = completePath .completer = completePath

View file

@ -15,8 +15,6 @@ namespace nix {
MixEvalArgs::MixEvalArgs() MixEvalArgs::MixEvalArgs()
{ {
auto category = "Common evaluation options";
addFlag({ addFlag({
.longName = "arg", .longName = "arg",
.description = "Pass the value *expr* as the argument *name* to Nix functions.", .description = "Pass the value *expr* as the argument *name* to Nix functions.",

View file

@ -11,6 +11,8 @@ struct SourcePath;
struct MixEvalArgs : virtual Args struct MixEvalArgs : virtual Args
{ {
static constexpr auto category = "Common evaluation options";
MixEvalArgs(); MixEvalArgs();
Bindings * getAutoArgs(EvalState & state); Bindings * getAutoArgs(EvalState & state);

View file

@ -1050,7 +1050,7 @@ struct CmdRepl : InstallablesCommand
evalSettings.pureEval = false; evalSettings.pureEval = false;
} }
void prepare() void prepare() override
{ {
if (!settings.isExperimentalFeatureEnabled(Xp::ReplFlake) && !(file) && this->_installables.size() >= 1) { if (!settings.isExperimentalFeatureEnabled(Xp::ReplFlake) && !(file) && this->_installables.size() >= 1) {
warn("future versions of Nix will require using `--file` to load a file"); warn("future versions of Nix will require using `--file` to load a file");

View file

@ -64,7 +64,7 @@ let
outputs = flake.outputs (inputs // { self = result; }); outputs = flake.outputs (inputs // { self = result; });
result = outputs // sourceInfo // { inherit inputs; inherit outputs; inherit sourceInfo; }; result = outputs // sourceInfo // { inherit inputs; inherit outputs; inherit sourceInfo; _type = "flake"; };
in in
if node.flake or true then if node.flake or true then
assert builtins.isFunction flake.outputs; assert builtins.isFunction flake.outputs;

View file

@ -3845,8 +3845,8 @@ static RegisterPrimOp primop_parseDrvName({
.args = {"s"}, .args = {"s"},
.doc = R"( .doc = R"(
Split the string *s* into a package name and version. The package Split the string *s* into a package name and version. The package
name is everything up to but not including the first dash followed name is everything up to but not including the first dash not followed
by a digit, and the version is everything following that dash. The by a letter, and the version is everything following that dash. The
result is returned in a set `{ name, version }`. Thus, result is returned in a set `{ name, version }`. Thus,
`builtins.parseDrvName "nix-0.12pre12876"` returns `{ name = `builtins.parseDrvName "nix-0.12pre12876"` returns `{ name =
"nix"; version = "0.12pre12876"; }`. "nix"; version = "0.12pre12876"; }`.

View file

@ -32,6 +32,7 @@ MixCommonArgs::MixCommonArgs(const std::string & programName)
addFlag({ addFlag({
.longName = "option", .longName = "option",
.description = "Set the Nix configuration setting *name* to *value* (overriding `nix.conf`).", .description = "Set the Nix configuration setting *name* to *value* (overriding `nix.conf`).",
.category = miscCategory,
.labels = {"name", "value"}, .labels = {"name", "value"},
.handler = {[](std::string name, std::string value) { .handler = {[](std::string name, std::string value) {
try { try {

View file

@ -6,6 +6,7 @@ namespace nix {
//static constexpr auto commonArgsCategory = "Miscellaneous common options"; //static constexpr auto commonArgsCategory = "Miscellaneous common options";
static constexpr auto loggingCategory = "Logging-related options"; static constexpr auto loggingCategory = "Logging-related options";
static constexpr auto miscCategory = "Miscellaneous global options";
class MixCommonArgs : public virtual Args class MixCommonArgs : public virtual Args
{ {

View file

@ -503,7 +503,7 @@ public:
return s[0]; return s[0];
} }
virtual void setPrintBuildLogs(bool printBuildLogs) void setPrintBuildLogs(bool printBuildLogs) override
{ {
this->printBuildLogs = printBuildLogs; this->printBuildLogs = printBuildLogs;
} }

View file

@ -113,5 +113,25 @@ struct PrintFreed
/* Install a SIGSEGV handler to detect stack overflows. */ /* Install a SIGSEGV handler to detect stack overflows. */
void detectStackOverflow(); void detectStackOverflow();
/* Pluggable behavior to run in case of a stack overflow.
Default value: defaultStackOverflowHandler.
This is called by the handler installed by detectStackOverflow().
This gives Nix library consumers a limit opportunity to report the error
condition. The handler should exit the process.
See defaultStackOverflowHandler() for a reference implementation.
NOTE: Use with diligence, because this runs in the signal handler, with very
limited stack space and a potentially a corrupted heap, all while the failed
thread is blocked indefinitely. All functions called must be reentrant. */
extern std::function<void(siginfo_t * info, void * ctx)> stackOverflowHandler;
/* The default, robust implementation of stackOverflowHandler.
Prints an error message directly to stderr using a syscall instead of the
logger. Exits the process immediately after. */
void defaultStackOverflowHandler(siginfo_t * info, void * ctx);
} }

View file

@ -1,4 +1,5 @@
#include "error.hh" #include "error.hh"
#include "shared.hh"
#include <cstring> #include <cstring>
#include <cstddef> #include <cstddef>
@ -29,9 +30,7 @@ static void sigsegvHandler(int signo, siginfo_t * info, void * ctx)
ptrdiff_t diff = (char *) info->si_addr - sp; ptrdiff_t diff = (char *) info->si_addr - sp;
if (diff < 0) diff = -diff; if (diff < 0) diff = -diff;
if (diff < 4096) { if (diff < 4096) {
char msg[] = "error: stack overflow (possible infinite recursion)\n"; nix::stackOverflowHandler(info, ctx);
[[gnu::unused]] auto res = write(2, msg, strlen(msg));
_exit(1); // maybe abort instead?
} }
} }
@ -67,5 +66,12 @@ void detectStackOverflow()
#endif #endif
} }
std::function<void(siginfo_t * info, void * ctx)> stackOverflowHandler(defaultStackOverflowHandler);
void defaultStackOverflowHandler(siginfo_t * info, void * ctx) {
char msg[] = "error: stack overflow (possible infinite recursion)\n";
[[gnu::unused]] auto res = write(2, msg, strlen(msg));
_exit(1); // maybe abort instead?
}
} }

View file

@ -331,6 +331,17 @@ bool BinaryCacheStore::isValidPathUncached(const StorePath & storePath)
return fileExists(narInfoFileFor(storePath)); return fileExists(narInfoFileFor(storePath));
} }
std::optional<StorePath> BinaryCacheStore::queryPathFromHashPart(const std::string & hashPart)
{
auto pseudoPath = StorePath(hashPart + "-" + MissingName);
try {
auto info = queryPathInfo(pseudoPath);
return info->path;
} catch (InvalidPath &) {
return std::nullopt;
}
}
void BinaryCacheStore::narFromPath(const StorePath & storePath, Sink & sink) void BinaryCacheStore::narFromPath(const StorePath & storePath, Sink & sink)
{ {
auto info = queryPathInfo(storePath).cast<const NarInfo>(); auto info = queryPathInfo(storePath).cast<const NarInfo>();

View file

@ -95,8 +95,7 @@ public:
void queryPathInfoUncached(const StorePath & path, void queryPathInfoUncached(const StorePath & path,
Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept override; Callback<std::shared_ptr<const ValidPathInfo>> callback) noexcept override;
std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) override std::optional<StorePath> queryPathFromHashPart(const std::string & hashPart) override;
{ unsupported("queryPathFromHashPart"); }
void addToStore(const ValidPathInfo & info, Source & narSource, void addToStore(const ValidPathInfo & info, Source & narSource,
RepairFlag repair, CheckSigsFlag checkSigs) override; RepairFlag repair, CheckSigsFlag checkSigs) override;

View file

@ -1594,6 +1594,8 @@ void LocalDerivationGoal::runChild()
/* Warning: in the child we should absolutely not make any SQLite /* Warning: in the child we should absolutely not make any SQLite
calls! */ calls! */
bool sendException = true;
try { /* child */ try { /* child */
commonChildInit(builderOut); commonChildInit(builderOut);
@ -2050,6 +2052,8 @@ void LocalDerivationGoal::runChild()
/* Indicate that we managed to set up the build environment. */ /* Indicate that we managed to set up the build environment. */
writeFull(STDERR_FILENO, std::string("\2\n")); writeFull(STDERR_FILENO, std::string("\2\n"));
sendException = false;
/* Execute the program. This should not return. */ /* Execute the program. This should not return. */
if (drv->isBuiltin()) { if (drv->isBuiltin()) {
try { try {
@ -2103,10 +2107,13 @@ void LocalDerivationGoal::runChild()
throw SysError("executing '%1%'", drv->builder); throw SysError("executing '%1%'", drv->builder);
} catch (Error & e) { } catch (Error & e) {
writeFull(STDERR_FILENO, "\1\n"); if (sendException) {
FdSink sink(STDERR_FILENO); writeFull(STDERR_FILENO, "\1\n");
sink << e; FdSink sink(STDERR_FILENO);
sink.flush(); sink << e;
sink.flush();
} else
std::cerr << e.msg();
_exit(1); _exit(1);
} }
} }

View file

@ -154,13 +154,9 @@ StringSet Settings::getDefaultExtraPlatforms()
// machines. Note that we cant force processes from executing // machines. Note that we cant force processes from executing
// x86_64 in aarch64 environments or vice versa since they can // x86_64 in aarch64 environments or vice versa since they can
// always exec with their own binary preferences. // always exec with their own binary preferences.
if (pathExists("/Library/Apple/System/Library/LaunchDaemons/com.apple.oahd.plist") || if (std::string{SYSTEM} == "aarch64-darwin" &&
pathExists("/System/Library/LaunchDaemons/com.apple.oahd.plist")) { runProgram(RunOptions {.program = "arch", .args = {"-arch", "x86_64", "/usr/bin/true"}, .mergeStderrToStdout = true}).first == 0)
if (std::string{SYSTEM} == "x86_64-darwin") extraPlatforms.insert("x86_64-darwin");
extraPlatforms.insert("aarch64-darwin");
else if (std::string{SYSTEM} == "aarch64-darwin")
extraPlatforms.insert("x86_64-darwin");
}
#endif #endif
return extraPlatforms; return extraPlatforms;

View file

@ -67,7 +67,7 @@ std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(const std::string
if (fakeSSH) { if (fakeSSH) {
args = { "bash", "-c" }; args = { "bash", "-c" };
} else { } else {
args = { "ssh", host.c_str(), "-x", "-a" }; args = { "ssh", host.c_str(), "-x" };
addCommonSSHOpts(args); addCommonSSHOpts(args);
if (socketPath != "") if (socketPath != "")
args.insert(args.end(), {"-S", socketPath}); args.insert(args.end(), {"-S", socketPath});

View file

@ -1367,9 +1367,9 @@ std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Para
} catch (Error & e) { } catch (Error & e) {
return std::make_shared<LocalStore>(params); return std::make_shared<LocalStore>(params);
} }
warn("'/nix' does not exist, so Nix will use '%s' as a chroot store", chrootStore); warn("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore);
} else } else
debug("'/nix' does not exist, so Nix will use '%s' as a chroot store", chrootStore); debug("'%s' does not exist, so Nix will use '%s' as a chroot store", stateDir, chrootStore);
Store::Params params2; Store::Params params2;
params2["root"] = chrootStore; params2["root"] = chrootStore;
return std::make_shared<LocalStore>(params2); return std::make_shared<LocalStore>(params2);

View file

@ -66,7 +66,9 @@ UnresolvedApp Installable::toApp(EvalState & state)
auto type = cursor->getAttr("type")->getString(); auto type = cursor->getAttr("type")->getString();
std::string expected = !attrPath.empty() && state.symbols[attrPath[0]] == "apps" ? "app" : "derivation"; std::string expected = !attrPath.empty() &&
(state.symbols[attrPath[0]] == "apps" || state.symbols[attrPath[0]] == "defaultApp")
? "app" : "derivation";
if (type != expected) if (type != expected)
throw Error("attribute '%s' should have type '%s'", cursor->getAttrPathStr(), expected); throw Error("attribute '%s' should have type '%s'", cursor->getAttrPathStr(), expected);

View file

@ -74,6 +74,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
addFlag({ addFlag({
.longName = "help", .longName = "help",
.description = "Show usage information.", .description = "Show usage information.",
.category = miscCategory,
.handler = {[&]() { throw HelpRequested(); }}, .handler = {[&]() { throw HelpRequested(); }},
}); });
@ -88,6 +89,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
addFlag({ addFlag({
.longName = "version", .longName = "version",
.description = "Show version information.", .description = "Show version information.",
.category = miscCategory,
.handler = {[&]() { showVersion = true; }}, .handler = {[&]() { showVersion = true; }},
}); });
@ -95,12 +97,14 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
.longName = "offline", .longName = "offline",
.aliases = {"no-net"}, // FIXME: remove .aliases = {"no-net"}, // FIXME: remove
.description = "Disable substituters and consider all previously downloaded files up-to-date.", .description = "Disable substituters and consider all previously downloaded files up-to-date.",
.category = miscCategory,
.handler = {[&]() { useNet = false; }}, .handler = {[&]() { useNet = false; }},
}); });
addFlag({ addFlag({
.longName = "refresh", .longName = "refresh",
.description = "Consider all previously downloaded files out-of-date.", .description = "Consider all previously downloaded files out-of-date.",
.category = miscCategory,
.handler = {[&]() { refresh = true; }}, .handler = {[&]() { refresh = true; }},
}); });
} }
@ -184,7 +188,7 @@ static void showHelp(std::vector<std::string> subcommand, MultiCommand & topleve
); );
auto attrs = state.buildBindings(16); auto attrs = state.buildBindings(16);
attrs.alloc("command").mkString(toplevel.toJSON().dump()); attrs.alloc("toplevel").mkString(toplevel.toJSON().dump());
auto vRes = state.allocValue(); auto vRes = state.allocValue();
state.callFunction(*vGenerateManpage, state.allocValue()->mkAttrs(attrs), *vRes, noPos); state.callFunction(*vGenerateManpage, state.allocValue()->mkAttrs(attrs), *vRes, noPos);

View file

@ -0,0 +1,39 @@
#include "command.hh"
#include "store-api.hh"
using namespace nix;
struct CmdPathFromHashPart : StoreCommand
{
std::string hashPart;
CmdPathFromHashPart()
{
expectArgs({
.label = "hash-part",
.handler = {&hashPart},
});
}
std::string description() override
{
return "get a store path from its hash part";
}
std::string doc() override
{
return
#include "path-from-hash-part.md"
;
}
void run(ref<Store> store) override
{
if (auto storePath = store->queryPathFromHashPart(hashPart))
logger->cout(store->printStorePath(*storePath));
else
throw Error("there is no store path corresponding to '%s'", hashPart);
}
};
static auto rCmdPathFromHashPart = registerCommand2<CmdPathFromHashPart>({"store", "path-from-hash-part"});

View file

@ -0,0 +1,20 @@
R""(
# Examples
* Return the full store path with the given hash part:
```console
# nix store path-from-hash-part --store https://cache.nixos.org/ 0i2jd68mp5g6h2sa5k9c85rb80sn8hi9
/nix/store/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9-hello-2.10
```
# Description
Given the hash part of a store path (that is, the 32 characters
following `/nix/store/`), return the full store path. This is
primarily useful in the implementation of binary caches, where a
request for a `.narinfo` file only supplies the hash part
(e.g. `https://cache.nixos.org/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9.narinfo`).
)""

View file

@ -36,7 +36,7 @@ R""(
Loading Installable ''... Loading Installable ''...
Added 1 variables. Added 1 variables.
# nix repl --extra_experimental_features 'flakes repl-flake' nixpkgs # nix repl --extra-experimental-features 'flakes repl-flake' nixpkgs
Loading Installable 'flake:nixpkgs#'... Loading Installable 'flake:nixpkgs#'...
Added 5 variables. Added 5 variables.

View file

@ -0,0 +1 @@
true

View file

@ -1 +0,0 @@
Bool(True)

View file

@ -4,6 +4,7 @@ let
name2 = "hello"; name2 = "hello";
name3 = "915resolution-0.5.2"; name3 = "915resolution-0.5.2";
name4 = "xf86-video-i810-1.7.4"; name4 = "xf86-video-i810-1.7.4";
name5 = "name-that-ends-with-dash--1.0";
eq = 0; eq = 0;
lt = builtins.sub 0 1; lt = builtins.sub 0 1;
@ -23,6 +24,8 @@ let
((builtins.parseDrvName name3).version == "0.5.2") ((builtins.parseDrvName name3).version == "0.5.2")
((builtins.parseDrvName name4).name == "xf86-video-i810") ((builtins.parseDrvName name4).name == "xf86-video-i810")
((builtins.parseDrvName name4).version == "1.7.4") ((builtins.parseDrvName name4).version == "1.7.4")
((builtins.parseDrvName name5).name == "name-that-ends-with-dash")
((builtins.parseDrvName name5).version == "-1.0")
(versionTest "1.0" "2.3" lt) (versionTest "1.0" "2.3" lt)
(versionTest "2.1" "2.3" lt) (versionTest "2.1" "2.3" lt)
(versionTest "2.3" "2.3" eq) (versionTest "2.3" "2.3" eq)

View file

@ -111,6 +111,7 @@ nix_tests = \
fetchClosure.sh \ fetchClosure.sh \
completions.sh \ completions.sh \
impure-derivations.sh \ impure-derivations.sh \
path-from-hash-part.sh \
toString-path.sh toString-path.sh
ifeq ($(HAVE_LIBCPUID), 1) ifeq ($(HAVE_LIBCPUID), 1)

View file

@ -0,0 +1,10 @@
source common.sh
path=$(nix build --no-link --print-out-paths -f simple.nix)
hash_part=$(basename $path)
hash_part=${hash_part:0:32}
path2=$(nix store path-from-hash-part $hash_part)
[[ $path = $path2 ]]