Merge branch 'master' into paths-from-stdin

This commit is contained in:
Théophane Hufschmitt 2023-03-02 19:20:51 +01:00 committed by GitHub
commit 1f394d2107
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 322 additions and 119 deletions

View file

@ -20,6 +20,8 @@ jobs:
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v19
with:
install_url: https://releases.nixos.org/nix/nix-2.13.3/install
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/cachix-action@v12
if: needs.check_secrets.outputs.cachix == 'true'
@ -59,6 +61,8 @@ jobs:
fetch-depth: 0
- run: echo CACHIX_NAME="$(echo $GITHUB_REPOSITORY-install-tests | tr "[A-Z]/" "[a-z]-")" >> $GITHUB_ENV
- uses: cachix/install-nix-action@v19
with:
install_url: https://releases.nixos.org/nix/nix-2.13.3/install
- uses: cachix/cachix-action@v12
with:
name: '${{ env.CACHIX_NAME }}'
@ -103,6 +107,8 @@ jobs:
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v19
with:
install_url: https://releases.nixos.org/nix/nix-2.13.3/install
- 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
- uses: cachix/cachix-action@v12

View file

@ -1 +1 @@
2.14.0
2.15.0

View file

@ -2,13 +2,10 @@ makefiles = \
mk/precompiled-headers.mk \
local.mk \
src/libutil/local.mk \
src/libutil/tests/local.mk \
src/libstore/local.mk \
src/libstore/tests/local.mk \
src/libfetchers/local.mk \
src/libmain/local.mk \
src/libexpr/local.mk \
src/libexpr/tests/local.mk \
src/libcmd/local.mk \
src/nix/local.mk \
src/resolve-system-dependencies/local.mk \
@ -19,12 +16,22 @@ makefiles = \
misc/systemd/local.mk \
misc/launchd/local.mk \
misc/upstart/local.mk \
doc/manual/local.mk \
tests/local.mk \
tests/plugins/local.mk
doc/manual/local.mk
-include Makefile.config
ifeq ($(tests), yes)
makefiles += \
src/libutil/tests/local.mk \
src/libstore/tests/local.mk \
src/libexpr/tests/local.mk \
tests/local.mk \
tests/plugins/local.mk
else
makefiles += \
mk/disable-tests.mk
endif
OPTIMIZE = 1
ifeq ($(OPTIMIZE), 1)

View file

@ -45,3 +45,4 @@ sandbox_shell = @sandbox_shell@
storedir = @storedir@
sysconfdir = @sysconfdir@
system = @system@
tests = @tests@

View file

@ -145,6 +145,13 @@ if test "x$GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC" = xyes; then
LDFLAGS="-latomic $LDFLAGS"
fi
# Building without tests is useful for bootstrapping with a smaller footprint
# or running the tests in a separate derivation. Otherwise, we do compile and
# run them.
AC_ARG_ENABLE(tests, AS_HELP_STRING([--disable-tests],[Do not build the tests]),
tests=$enableval, tests=yes)
AC_SUBST(tests)
# LTO is currently broken with clang for unknown reasons; ld segfaults in the llvm plugin
AC_ARG_ENABLE(lto, AS_HELP_STRING([--enable-lto],[Enable LTO (only supported with GCC) [default=no]]),
lto=$enableval, lto=no)
@ -270,6 +277,8 @@ if test "$gc" = yes; then
fi
if test "$tests" = yes; then
# Look for gtest.
PKG_CHECK_MODULES([GTEST], [gtest_main])
@ -282,6 +291,7 @@ dnl No good for C++ libs with mangled symbols
dnl AC_CHECK_LIB([rapidcheck], [])
AC_LANG_POP(C++)
fi
# Look for nlohmann/json.
PKG_CHECK_MODULES([NLOHMANN_JSON], [nlohmann_json >= 3.9])

View file

@ -71,3 +71,8 @@
<http://libcpuid.sourceforge.net>.
This is an optional dependency and can be disabled
by providing a `--disable-cpuid` to the `configure` script.
- Unless `./configure --disable-tests` is specified, GoogleTest (GTest) and
RapidCheck are required, which are available at
<https://google.github.io/googletest/> and
<https://github.com/emil-e/rapidcheck> respectively.

View file

@ -3,3 +3,20 @@
* Commands which take installables on the command line can now read them from the standard input if
passed the `--stdin` flag. This is primarily useful when you have a large amount of paths which
exceed the OS arg limit.
* The special handling of an [installable](../command-ref/new-cli/nix.md#installables) with `.drv` suffix being interpreted as all of the given [store derivation](../glossary.md#gloss-store-derivation)'s output paths is removed, and instead taken as the literal store path that it represents.
The new `^` syntax for store paths introduced in Nix 2.13 allows explicitly referencing output paths of a derivation.
Using this is better and more clear than relying on the now-removed `.drv` special handling.
For example,
```shell-session
$ nix path-info /nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv
```
now gives info about the derivation itself, while
```shell-session
$ nix path-info /nix/store/gzaflydcr6sb3567hap9q6srzx8ggdgg-glibc-2.33-78.drv^*
```
provides information about each of its outputs.

View file

@ -89,9 +89,7 @@
});
configureFlags =
[
"CXXFLAGS=-I${lib.getDev rapidcheck}/extras/gtest/include"
] ++ lib.optionals stdenv.isLinux [
lib.optionals stdenv.isLinux [
"--with-boost=${boost}/lib"
"--with-sandbox-shell=${sh}/bin/busybox"
]
@ -99,6 +97,10 @@
"LDFLAGS=-fuse-ld=gold"
];
testConfigureFlags = [
"CXXFLAGS=-I${lib.getDev rapidcheck}/extras/gtest/include"
];
nativeBuildDeps =
[
buildPackages.bison
@ -124,13 +126,16 @@
libarchive
boost
lowdown-nix
gtest
rapidcheck
]
++ lib.optionals stdenv.isLinux [libseccomp]
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid;
checkDeps = [
gtest
rapidcheck
];
awsDeps = lib.optional (stdenv.isLinux || stdenv.isDarwin)
(aws-sdk-cpp.override {
apis = ["s3" "transfer"];
@ -200,7 +205,7 @@
VERSION_SUFFIX = versionSuffix;
nativeBuildInputs = nativeBuildDeps;
buildInputs = buildDeps ++ awsDeps;
buildInputs = buildDeps ++ awsDeps ++ checkDeps;
propagatedBuildInputs = propagatedDeps;
enableParallelBuilding = true;
@ -305,7 +310,7 @@
};
let
canRunInstalled = currentStdenv.buildPlatform.canExecute currentStdenv.hostPlatform;
in currentStdenv.mkDerivation {
in currentStdenv.mkDerivation (finalAttrs: {
name = "nix-${version}";
inherit version;
@ -318,7 +323,8 @@
nativeBuildInputs = nativeBuildDeps;
buildInputs = buildDeps
# There have been issues building these dependencies
++ lib.optionals (currentStdenv.hostPlatform == currentStdenv.buildPlatform) awsDeps;
++ lib.optionals (currentStdenv.hostPlatform == currentStdenv.buildPlatform) awsDeps
++ lib.optionals finalAttrs.doCheck checkDeps;
propagatedBuildInputs = propagatedDeps;
@ -348,6 +354,8 @@
configureFlags = configureFlags ++
[ "--sysconfdir=/etc" ] ++
lib.optional stdenv.hostPlatform.isStatic "--enable-embedded-sandbox-shell" ++
[ (lib.enableFeature finalAttrs.doCheck "tests") ] ++
lib.optionals finalAttrs.doCheck testConfigureFlags ++
lib.optional (!canRunInstalled) "--disable-doc-gen";
enableParallelBuilding = true;
@ -369,7 +377,7 @@
''}
'';
doInstallCheck = true;
doInstallCheck = finalAttrs.doCheck;
installCheckFlags = "sysconfdir=$(out)/etc";
separateDebugInfo = !currentStdenv.hostPlatform.isStatic;
@ -411,7 +419,7 @@
});
meta.platforms = lib.platforms.unix;
};
});
lowdown-nix = with final; currentStdenv.mkDerivation rec {
name = "lowdown-0.9.0";
@ -462,6 +470,14 @@
buildNoGc = forAllSystems (system: self.packages.${system}.nix.overrideAttrs (a: { configureFlags = (a.configureFlags or []) ++ ["--enable-gc=no"];}));
buildNoTests = forAllSystems (system:
self.packages.${system}.nix.overrideAttrs (a: {
doCheck =
assert ! a?dontCheck;
false;
})
);
# Perl bindings for various platforms.
perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nix.perl-bindings);
@ -634,9 +650,9 @@
nativeBuildInputs = nativeBuildDeps
++ (lib.optionals stdenv.cc.isClang [ pkgs.bear pkgs.clang-tools ]);
buildInputs = buildDeps ++ propagatedDeps ++ awsDeps;
buildInputs = buildDeps ++ propagatedDeps ++ awsDeps ++ checkDeps;
inherit configureFlags;
configureFlags = configureFlags ++ testConfigureFlags;
enableParallelBuilding = true;

View file

@ -123,6 +123,7 @@ release:
`/home/eelco/Dev/nixpkgs-pristine`.
TODO: trigger nixos.org netlify: https://docs.netlify.com/configure-builds/build-hooks/
* Prepare for the next point release by editing `.version` to
e.g.
@ -152,7 +153,7 @@ release:
from the previous milestone, and close the previous milestone. Set
the date for the next milestone 6 weeks from now.
* Create a backport label
* Create a backport label.
* Post an [announcement on Discourse](https://discourse.nixos.org/c/announcements/8), including the contents of
`rl-$VERSION.md`.

12
mk/disable-tests.mk Normal file
View file

@ -0,0 +1,12 @@
# This file is only active for `./configure --disable-tests`.
# Running `make check` or `make installcheck` would indicate a mistake in the
# caller.
installcheck:
@echo "Tests are disabled. Configure without '--disable-tests', or avoid calling 'make installcheck'."
@exit 1
# This currently has little effect.
check:
@echo "Tests are disabled. Configure without '--disable-tests', or avoid calling 'make check'."
@exit 1

View file

@ -8,7 +8,7 @@ if [ -n "${XDG_STATE_HOME-}" ]; then
else
NIX_LINK_NEW=$HOME/.local/state/nix/profile
fi
if ! [ -e "$NIX_LINK" ]; then
if [ -e "$NIX_LINK_NEW" ]; then
NIX_LINK="$NIX_LINK_NEW"
else
if [ -t 2 ] && [ -e "$NIX_LINK_NEW" ]; then

View file

@ -8,7 +8,7 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then
else
NIX_LINK_NEW="$HOME/.local/state/nix/profile"
fi
if ! [ -e "$NIX_LINK" ]; then
if [ -e "$NIX_LINK_NEW" ]; then
NIX_LINK="$NIX_LINK_NEW"
else
if [ -t 2 ] && [ -e "$NIX_LINK_NEW" ]; then

View file

@ -31,27 +31,24 @@ InstallableDerivedPath InstallableDerivedPath::parse(
ExtendedOutputsSpec extendedOutputsSpec)
{
auto derivedPath = std::visit(overloaded {
// If the user did not use ^, we treat the output more liberally.
// If the user did not use ^, we treat the output more
// liberally: we accept a symlink chain or an actual
// store path.
[&](const ExtendedOutputsSpec::Default &) -> DerivedPath {
// First, we accept a symlink chain or an actual store path.
auto storePath = store->followLinksToStorePath(prefix);
// Second, we see if the store path ends in `.drv` to decide what sort
// of derived path they want.
//
// This handling predates the `^` syntax. The `^*` in
// `/nix/store/hash-foo.drv^*` unambiguously means "do the
// `DerivedPath::Built` case", so plain `/nix/store/hash-foo.drv` could
// also unambiguously mean "do the DerivedPath::Opaque` case".
//
// Issue #7261 tracks reconsidering this `.drv` dispatching.
return storePath.isDerivation()
? (DerivedPath) DerivedPath::Built {
.drvPath = std::move(storePath),
.outputs = OutputsSpec::All {},
}
: (DerivedPath) DerivedPath::Opaque {
.path = std::move(storePath),
// Remove this prior to stabilizing the new CLI.
if (storePath.isDerivation()) {
auto oldDerivedPath = DerivedPath::Built {
.drvPath = storePath,
.outputs = OutputsSpec::All { },
};
warn(
"The interpretation of store paths arguments ending in `.drv` recently changed. If this command is now failing try again with '%s'",
oldDerivedPath.to_string(*store));
};
return DerivedPath::Opaque {
.path = std::move(storePath),
};
},
// If the user did use ^, we just do exactly what is written.
[&](const ExtendedOutputsSpec::Explicit & outputSpec) -> DerivedPath {

View file

@ -677,9 +677,12 @@ StorePathSet Installable::toDerivations(
for (const auto & b : i->toDerivedPaths())
std::visit(overloaded {
[&](const DerivedPath::Opaque & bo) {
if (!useDeriver)
throw Error("argument '%s' did not evaluate to a derivation", i->what());
drvPaths.insert(getDeriver(store, *i, bo.path));
drvPaths.insert(
bo.path.isDerivation()
? bo.path
: useDeriver
? getDeriver(store, *i, bo.path)
: throw Error("argument '%s' did not evaluate to a derivation", i->what()));
},
[&](const DerivedPath::Built & bfd) {
drvPaths.insert(bfd.drvPath);

View file

@ -63,6 +63,11 @@ public:
one that contains a commit hash or content hash. */
bool isLocked() const { return locked; }
/* Check whether the input carries all necessary info required
for cache insertion and substitution.
These fields are used to uniquely identify cached trees
within the "tarball TTL" window without necessarily
indicating that the input's origin is unchanged. */
bool hasAllInfo() const;
bool operator ==(const Input & other) const;

View file

@ -92,13 +92,11 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
if (S_ISLNK(dstSt.st_mode)) {
auto prevPriority = state.priorities[dstFile];
if (prevPriority == priority)
throw Error(
"files '%1%' and '%2%' have the same priority %3%; "
"use 'nix-env --set-flag priority NUMBER INSTALLED_PKGNAME' "
"or type 'nix profile install --help' if using 'nix profile' to find out how "
"to change the priority of one of the conflicting packages"
" (0 being the highest priority)",
srcFile, readLink(dstFile), priority);
throw BuildEnvFileConflictError(
readLink(dstFile),
srcFile,
priority
);
if (prevPriority < priority)
continue;
if (unlink(dstFile.c_str()) == -1)

View file

@ -12,6 +12,32 @@ struct Package {
Package(const Path & path, bool active, int priority) : path{path}, active{active}, priority{priority} {}
};
class BuildEnvFileConflictError : public Error
{
public:
const Path fileA;
const Path fileB;
int priority;
BuildEnvFileConflictError(
const Path fileA,
const Path fileB,
int priority
)
: Error(
"Unable to build profile. There is a conflict for the following files:\n"
"\n"
" %1%\n"
" %2%",
fileA,
fileB
)
, fileA(fileA)
, fileB(fileB)
, priority(priority)
{}
};
typedef std::vector<Package> Packages;
void buildProfile(const Path & out, Packages && pkgs);

View file

@ -88,6 +88,10 @@ struct curlFileTransfer : public FileTransfer
{request.uri}, request.parentAct)
, callback(std::move(callback))
, finalSink([this](std::string_view data) {
if (errorSink) {
(*errorSink)(data);
}
if (this->request.dataCallback) {
auto httpStatus = getHTTPStatus();
@ -163,8 +167,6 @@ struct curlFileTransfer : public FileTransfer
}
}
if (errorSink)
(*errorSink)({(char *) contents, realSize});
(*decompressionSink)({(char *) contents, realSize});
return realSize;

View file

@ -38,8 +38,6 @@ class RemoteStore : public virtual RemoteStoreConfig,
{
public:
virtual bool sameMachine() = 0;
RemoteStore(const Params & params);
/* Implementations of abstract store API methods. */

View file

@ -49,9 +49,6 @@ public:
return *uriSchemes().begin() + "://" + host;
}
bool sameMachine() override
{ return false; }
// FIXME extend daemon protocol, move implementation to RemoteStore
std::optional<std::string> getBuildLogExact(const StorePath & path) override
{ unsupported("getBuildLogExact"); }

View file

@ -855,6 +855,7 @@ json Store::pathInfoToJSON(const StorePathSet & storePaths,
auto info = queryPathInfo(storePath);
jsonPath["path"] = printStorePath(info->path);
jsonPath["valid"] = true;
jsonPath["narHash"] = info->narHash.to_string(hashBase, true);
jsonPath["narSize"] = info->narSize;

View file

@ -29,9 +29,6 @@ public:
static std::set<std::string> uriSchemes()
{ return {"unix"}; }
bool sameMachine() override
{ return true; }
ref<FSAccessor> getFSAccessor() override
{ return LocalFSStore::getFSAccessor(); }

View file

@ -32,7 +32,8 @@ void Logger::warn(const std::string & msg)
void Logger::writeToStdout(std::string_view s)
{
std::cout << s << "\n";
writeFull(STDOUT_FILENO, s);
writeFull(STDOUT_FILENO, "\n");
}
class SimpleLogger : public Logger
@ -84,7 +85,7 @@ public:
void startActivity(ActivityId act, Verbosity lvl, ActivityType type,
const std::string & s, const Fields & fields, ActivityId parent)
override
override
{
if (lvl <= verbosity && !s.empty())
log(lvl, s + "...");

View file

@ -102,11 +102,9 @@ public:
virtual void writeToStdout(std::string_view s);
template<typename... Args>
inline void cout(const std::string & fs, const Args & ... args)
inline void cout(const Args & ... args)
{
boost::format f(fs);
formatHelper(f, args...);
writeToStdout(f.str());
writeToStdout(fmt(args...));
}
virtual std::optional<char> ask(std::string_view s)

View file

@ -139,11 +139,11 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
for (auto & buildable : buildables) {
std::visit(overloaded {
[&](const BuiltPath::Opaque & bo) {
std::cout << store->printStorePath(bo.path) << std::endl;
logger->cout(store->printStorePath(bo.path));
},
[&](const BuiltPath::Built & bfd) {
for (auto & output : bfd.outputs) {
std::cout << store->printStorePath(output.second) << std::endl;
logger->cout(store->printStorePath(output.second));
}
},
}, buildable.path.raw());

View file

@ -17,7 +17,7 @@ struct MixCat : virtual Args
if (st.type != FSAccessor::Type::tRegular)
throw Error("path '%1%' is not a regular file", path);
std::cout << accessor->readFile(path);
writeFull(STDOUT_FILENO, accessor->readFile(path));
}
};

View file

@ -25,7 +25,7 @@ struct CmdDescribeStores : Command, MixJSON
res[storeName] = storeConfig->toJSON();
}
if (json) {
std::cout << res;
logger->cout("%s", res);
} else {
for (auto & [storeName, storeConfig] : res.items()) {
std::cout << "## " << storeName << std::endl << std::endl;

View file

@ -97,7 +97,7 @@ void printClosureDiff(
items.push_back(fmt("%s → %s", showVersions(removed), showVersions(added)));
if (showDelta)
items.push_back(fmt("%s%+.1f KiB" ANSI_NORMAL, sizeDelta > 0 ? ANSI_RED : ANSI_GREEN, sizeDelta / 1024.0));
std::cout << fmt("%s%s: %s\n", indent, name, concatStringsSep(", ", items));
logger->cout("%s%s: %s", indent, name, concatStringsSep(", ", items));
}
}
}

View file

@ -112,11 +112,11 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption
else if (raw) {
stopProgressBar();
std::cout << *state->coerceToString(noPos, *v, context, "while generating the eval command output");
writeFull(STDOUT_FILENO, *state->coerceToString(noPos, *v, context, "while generating the eval command output"));
}
else if (json) {
std::cout << printValueAsJSON(*state, true, *v, pos, context, false).dump() << std::endl;
logger->cout("%s", printValueAsJSON(*state, true, *v, pos, context, false));
}
else {

View file

@ -952,7 +952,7 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun
{"path", store->printStorePath(flake.flake.sourceInfo->storePath)},
{"inputs", traverse(*flake.lockFile.root)},
};
std::cout << jsonRoot.dump() << std::endl;
logger->cout("%s", jsonRoot);
} else {
traverse(*flake.lockFile.root);
}

View file

@ -53,7 +53,7 @@ struct CmdLog : InstallableCommand
if (!log) continue;
stopProgressBar();
printInfo("got build log for '%s' from '%s'", installable->what(), logSub.getUri());
std::cout << *log;
writeFull(STDOUT_FILENO, *log);
return;
}

View file

@ -93,7 +93,7 @@ struct MixLs : virtual Args, MixJSON
if (json) {
if (showDirectory)
throw UsageError("'--directory' is useless with '--json'");
std::cout << listNar(accessor, path, recursive);
logger->cout("%s", listNar(accessor, path, recursive));
} else
listText(accessor);
}

View file

@ -292,7 +292,7 @@ void mainWrapped(int argc, char * * argv)
NixArgs args;
if (argc == 2 && std::string(argv[1]) == "__dump-args") {
std::cout << args.toJSON().dump() << "\n";
logger->cout("%s", args.toJSON());
return;
}
@ -312,7 +312,7 @@ void mainWrapped(int argc, char * * argv)
b["doc"] = trim(stripIndentation(primOp->doc));
res[state.symbols[builtin.name]] = std::move(b);
}
std::cout << res.dump() << "\n";
logger->cout("%s", res);
return;
}
@ -321,14 +321,14 @@ void mainWrapped(int argc, char * * argv)
if (completions) {
switch (completionType) {
case ctNormal:
std::cout << "normal\n"; break;
logger->cout("normal"); break;
case ctFilenames:
std::cout << "filenames\n"; break;
logger->cout("filenames"); break;
case ctAttrs:
std::cout << "attrs\n"; break;
logger->cout("attrs"); break;
}
for (auto & s : *completions)
std::cout << s.completion << "\t" << trim(s.description) << "\n";
logger->cout(s.completion + "\t" + trim(s.description));
}
});

View file

@ -45,7 +45,7 @@ struct CmdMakeContentAddressed : virtual CopyCommand, virtual StorePathsCommand,
}
auto json = json::object();
json["rewrites"] = jsonRewrites;
std::cout << json.dump();
logger->cout("%s", json);
} else {
for (auto & path : storePaths) {
auto i = remappings.find(path);

View file

@ -234,9 +234,9 @@ static int main_nix_prefetch_url(int argc, char * * argv)
if (!printPath)
printInfo("path is '%s'", store->printStorePath(storePath));
std::cout << printHash16or32(hash) << std::endl;
logger->cout(printHash16or32(hash));
if (printPath)
std::cout << store->printStorePath(storePath) << std::endl;
logger->cout(store->printStorePath(storePath));
return 0;
}

View file

@ -228,12 +228,12 @@ struct ProfileManifest
while (i != prevElems.end() || j != curElems.end()) {
if (j != curElems.end() && (i == prevElems.end() || i->describe() > j->describe())) {
std::cout << fmt("%s%s: ∅ -> %s\n", indent, j->describe(), j->versions());
logger->cout("%s%s: ∅ -> %s", indent, j->describe(), j->versions());
changes = true;
++j;
}
else if (i != prevElems.end() && (j == curElems.end() || i->describe() < j->describe())) {
std::cout << fmt("%s%s: %s -> ∅\n", indent, i->describe(), i->versions());
logger->cout("%s%s: %s -> ∅", indent, i->describe(), i->versions());
changes = true;
++i;
}
@ -241,7 +241,7 @@ struct ProfileManifest
auto v1 = i->versions();
auto v2 = j->versions();
if (v1 != v2) {
std::cout << fmt("%s%s: %s -> %s\n", indent, i->describe(), v1, v2);
logger->cout("%s%s: %s -> %s", indent, i->describe(), v1, v2);
changes = true;
}
++i;
@ -250,7 +250,7 @@ struct ProfileManifest
}
if (!changes)
std::cout << fmt("%sNo changes.\n", indent);
logger->cout("%sNo changes.", indent);
}
};
@ -330,7 +330,63 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
manifest.elements.push_back(std::move(element));
}
updateProfile(manifest.build(store));
try {
updateProfile(manifest.build(store));
} catch (BuildEnvFileConflictError & conflictError) {
// FIXME use C++20 std::ranges once macOS has it
// See https://github.com/NixOS/nix/compare/3efa476c5439f8f6c1968a6ba20a31d1239c2f04..1fe5d172ece51a619e879c4b86f603d9495cc102
auto findRefByFilePath = [&]<typename Iterator>(Iterator begin, Iterator end) {
for (auto it = begin; it != end; it++) {
auto profileElement = *it;
for (auto & storePath : profileElement.storePaths) {
if (conflictError.fileA.starts_with(store->printStorePath(storePath))) {
return std::pair(conflictError.fileA, profileElement.source->originalRef);
}
if (conflictError.fileB.starts_with(store->printStorePath(storePath))) {
return std::pair(conflictError.fileB, profileElement.source->originalRef);
}
}
}
throw conflictError;
};
// There are 2 conflicting files. We need to find out which one is from the already installed package and
// which one is the package that is the new package that is being installed.
// The first matching package is the one that was already installed (original).
auto [originalConflictingFilePath, originalConflictingRef] = findRefByFilePath(manifest.elements.begin(), manifest.elements.end());
// The last matching package is the one that was going to be installed (new).
auto [newConflictingFilePath, newConflictingRef] = findRefByFilePath(manifest.elements.rbegin(), manifest.elements.rend());
throw Error(
"An existing package already provides the following file:\n"
"\n"
" %1%\n"
"\n"
"This is the conflicting file from the new package:\n"
"\n"
" %2%\n"
"\n"
"To remove the existing package:\n"
"\n"
" nix profile remove %3%\n"
"\n"
"The new package can also be installed next to the existing one by assigning a different priority.\n"
"The conflicting packages have a priority of %5%.\n"
"To prioritise the new package:\n"
"\n"
" nix profile install %4% --priority %6%\n"
"\n"
"To prioritise the existing package:\n"
"\n"
" nix profile install %4% --priority %7%\n",
originalConflictingFilePath,
newConflictingFilePath,
originalConflictingRef.to_string(),
newConflictingRef.to_string(),
conflictError.priority,
conflictError.priority - 1,
conflictError.priority + 1
);
}
}
};
@ -584,9 +640,9 @@ struct CmdProfileDiffClosures : virtual StoreCommand, MixDefaultProfile
for (auto & gen : gens) {
if (prevGen) {
if (!first) std::cout << "\n";
if (!first) logger->cout("");
first = false;
std::cout << fmt("Version %d -> %d:\n", prevGen->number, gen.number);
logger->cout("Version %d -> %d:", prevGen->number, gen.number);
printClosureDiff(store,
store->followLinksToStorePath(prevGen->path),
store->followLinksToStorePath(gen.path),
@ -622,10 +678,10 @@ struct CmdProfileHistory : virtual StoreCommand, EvalCommand, MixDefaultProfile
for (auto & gen : gens) {
ProfileManifest manifest(*getEvalState(), gen.path);
if (!first) std::cout << "\n";
if (!first) logger->cout("");
first = false;
std::cout << fmt("Version %s%d" ANSI_NORMAL " (%s)%s:\n",
logger->cout("Version %s%d" ANSI_NORMAL " (%s)%s:",
gen.number == curGen ? ANSI_GREEN : ANSI_BOLD,
gen.number,
std::put_time(std::gmtime(&gen.creationTime), "%Y-%m-%d"),

View file

@ -65,18 +65,16 @@ struct CmdRealisationInfo : BuiltPathsCommand, MixJSON
res.push_back(currentPath);
}
std::cout << res.dump();
logger->cout("%s", res);
}
else {
for (auto & path : realisations) {
if (auto realisation = std::get_if<Realisation>(&path.raw)) {
std::cout <<
realisation->id.to_string() << " " <<
store->printStorePath(realisation->outPath);
logger->cout("%s %s",
realisation->id.to_string(),
store->printStorePath(realisation->outPath));
} else
std::cout << store->printStorePath(path.path());
std::cout << std::endl;
logger->cout("%s", store->printStorePath(path.path()));
}
}
}

View file

@ -196,9 +196,8 @@ struct CmdSearch : InstallableCommand, MixJSON
for (auto & cursor : installable->getCursors(*state))
visit(*cursor, cursor->getAttrPath(), true);
if (json) {
std::cout << jsonOut->dump() << std::endl;
}
if (json)
logger->cout("%s", *jsonOut);
if (!json && !results)
throw Error("no results for the given search term(s)!");

View file

@ -57,7 +57,7 @@ struct CmdShowDerivation : InstallablesCommand
jsonRoot[store->printStorePath(drvPath)] =
store->readDerivation(drvPath).toJSON(*store);
}
std::cout << jsonRoot.dump(2) << std::endl;
logger->cout(jsonRoot.dump(2));
}
};

View file

@ -173,7 +173,7 @@ struct CmdKeyGenerateSecret : Command
if (!keyName)
throw UsageError("required argument '--key-name' is missing");
std::cout << SecretKey::generate(*keyName).to_string();
writeFull(STDOUT_FILENO, SecretKey::generate(*keyName).to_string());
}
};
@ -194,7 +194,7 @@ struct CmdKeyConvertSecretToPublic : Command
void run() override
{
SecretKey secretKey(drainFD(STDIN_FILENO));
std::cout << secretKey.toPublicKey().to_string();
writeFull(STDOUT_FILENO, secretKey.toPublicKey().to_string());
}
};

View file

@ -23,7 +23,7 @@ nix log $outPath 2>&1 | grep 'is not available'
nix log --substituters file://$cacheDir $outPath | grep FOO
# Test copying build logs from the binary cache.
nix store copy-log --from file://$cacheDir $(nix-store -qd $outPath)
nix store copy-log --from file://$cacheDir $(nix-store -qd $outPath)^'*'
nix log $outPath | grep FOO
basicDownloadTests() {

View file

@ -2,14 +2,14 @@
source common.sh
drv=$(nix-instantiate --experimental-features ca-derivations ./content-addressed.nix -A rootCA --arg seed 1)
nix --experimental-features 'nix-command ca-derivations' show-derivation "$drv" --arg seed 1
drv=$(nix-instantiate ./content-addressed.nix -A rootCA --arg seed 1)
nix show-derivation "$drv" --arg seed 1
buildAttr () {
local derivationPath=$1
local seedValue=$2
shift; shift
local args=("--experimental-features" "ca-derivations" "./content-addressed.nix" "-A" "$derivationPath" --arg seed "$seedValue" "--no-out-link")
local args=("./content-addressed.nix" "-A" "$derivationPath" --arg seed "$seedValue" "--no-out-link")
args+=("$@")
nix-build "${args[@]}"
}
@ -46,17 +46,17 @@ testCutoff () {
}
testGC () {
nix-instantiate --experimental-features ca-derivations ./content-addressed.nix -A rootCA --arg seed 5
nix-collect-garbage --experimental-features ca-derivations --option keep-derivations true
nix-instantiate ./content-addressed.nix -A rootCA --arg seed 5
nix-collect-garbage --option keep-derivations true
clearStore
buildAttr rootCA 1 --out-link $TEST_ROOT/rootCA
nix-collect-garbage --experimental-features ca-derivations
nix-collect-garbage
buildAttr rootCA 1 -j0
}
testNixCommand () {
clearStore
nix build --experimental-features 'nix-command ca-derivations' --file ./content-addressed.nix --no-link
nix build --file ./content-addressed.nix --no-link
}
# Regression test for https://github.com/NixOS/nix/issues/4775

View file

@ -28,6 +28,12 @@ nix realisation info --file ./content-addressed.nix transitivelyDependentCA
nix realisation info --file ./content-addressed.nix dependentCA
# nix realisation info --file ./content-addressed.nix rootCA --outputs out
if isDaemonNewer "2.13"; then
pushToStore="../push-to-store.sh"
else
pushToStore="../push-to-store-old.sh"
fi
# Same thing, but
# 1. With non-ca derivations
# 2. Erasing the realisations on the remote store
@ -37,7 +43,7 @@ nix realisation info --file ./content-addressed.nix dependentCA
#
# Regression test for #4725
clearStore
nix build --file ../simple.nix -L --no-link --post-build-hook ../push-to-store.sh
nix build --file ../simple.nix -L --no-link --post-build-hook "$pushToStore"
clearStore
rm -r "$REMOTE_STORE_DIR/realisations"
nix build --file ../simple.nix -L --no-link --substitute --substituters "$REMOTE_STORE" --no-require-sigs -j0
@ -52,7 +58,7 @@ if [[ -z "$(ls "$REMOTE_STORE_DIR/realisations")" ]]; then
fi
# Test the local realisation disk cache
buildDrvs --post-build-hook ../push-to-store.sh
buildDrvs --post-build-hook "$pushToStore"
clearStore
# Add the realisations of rootCA to the cachecache
clearCacheCache

View file

@ -140,6 +140,36 @@ printf World2 > $flake2Dir/who
nix profile install $flake1Dir
[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]]
expect 1 nix profile install $flake2Dir
diff -u <(
nix --offline profile install $flake2Dir 2>&1 1> /dev/null \
| grep -vE "^warning: " \
|| true
) <(cat << EOF
error: An existing package already provides the following file:
$(nix build --no-link --print-out-paths ${flake1Dir}"#default.out")/bin/hello
This is the conflicting file from the new package:
$(nix build --no-link --print-out-paths ${flake2Dir}"#default.out")/bin/hello
To remove the existing package:
nix profile remove path:${flake1Dir}
The new package can also be installed next to the existing one by assigning a different priority.
The conflicting packages have a priority of 5.
To prioritise the new package:
nix profile install path:${flake2Dir} --priority 4
To prioritise the existing package:
nix profile install path:${flake2Dir} --priority 6
EOF
)
[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]]
nix profile install $flake2Dir --priority 100
[[ $($TEST_HOME/.nix-profile/bin/hello) = "Hello World" ]]
nix profile install $flake2Dir --priority 0

View file

@ -9,8 +9,14 @@ echo 'require-sigs = false' >> $NIX_CONF_DIR/nix.conf
restartDaemon
if isDaemonNewer "2.13"; then
pushToStore="$PWD/push-to-store.sh"
else
pushToStore="$PWD/push-to-store-old.sh"
fi
# Build the dependencies and push them to the remote store.
nix-build -o $TEST_ROOT/result dependencies.nix --post-build-hook $PWD/push-to-store.sh
nix-build -o $TEST_ROOT/result dependencies.nix --post-build-hook "$pushToStore"
clearStore

10
tests/push-to-store-old.sh Executable file
View file

@ -0,0 +1,10 @@
#!/bin/sh
set -x
set -e
[ -n "$OUT_PATHS" ]
[ -n "$DRV_PATH" ]
echo Pushing "$OUT_PATHS" to "$REMOTE_STORE"
printf "%s" "$DRV_PATH" | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs

View file

@ -7,4 +7,4 @@ set -e
[ -n "$DRV_PATH" ]
echo Pushing "$OUT_PATHS" to "$REMOTE_STORE"
printf "%s" "$DRV_PATH" | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs
printf "%s" "$DRV_PATH"^'*' | xargs nix copy --to "$REMOTE_STORE" --no-require-sigs