Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package nix for openSUSE:Factory checked in 
at 2026-03-22 14:12:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/nix (Old)
 and      /work/SRC/openSUSE:Factory/.nix.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "nix"

Sun Mar 22 14:12:52 2026 rev:14 rq:1341727 version:2.34.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/nix/nix.changes  2026-03-19 17:37:59.435334101 
+0100
+++ /work/SRC/openSUSE:Factory/.nix.new.8177/nix.changes        2026-03-22 
14:14:10.850224365 +0100
@@ -1,0 +2,7 @@
+Fri Mar 20 11:24:04 UTC 2026 - Marcus Rueckert <[email protected]>
+
+- Update to version 2.34.2:
+  see /usr/share/doc/packages/rl-2.34.md
+- drop de426e1a3.patch: included in upstream
+
+-------------------------------------------------------------------

Old:
----
  de426e1a3.patch
  nix-2.34.1.tar.gz

New:
----
  nix-2.34.2.tar.gz

----------(Old B)----------
  Old:  see /usr/share/doc/packages/rl-2.34.md
- drop de426e1a3.patch: included in upstream
----------(Old E)----------

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ nix.spec ++++++
--- /var/tmp/diff_new_pack.wgElWk/_old  2026-03-22 14:14:11.418247730 +0100
+++ /var/tmp/diff_new_pack.wgElWk/_new  2026-03-22 14:14:11.418247730 +0100
@@ -26,7 +26,7 @@
 %endif
 
 Name:           nix
-Version:        2.34.1
+Version:        2.34.2
 Release:        0
 Summary:        The purely functional package manager
 License:        LGPL-2.1-only
@@ -36,7 +36,6 @@
 Source2:        sysusers.conf
 Source9:        series
 Patch1:         0001-port-option-to-disable-functional-tests-to-meson.patch
-Patch2:         de426e1a3.patch
 BuildRequires:  bison
 BuildRequires:  boost-devel
 BuildRequires:  busybox-static

++++++ nix-2.34.1.tar.gz -> nix-2.34.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nix-2.34.1/.version new/nix-2.34.2/.version
--- old/nix-2.34.1/.version     2026-03-08 11:43:50.000000000 +0100
+++ new/nix-2.34.2/.version     2026-03-19 23:47:16.000000000 +0100
@@ -1 +1 @@
-2.34.1
+2.34.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/nix-2.34.1/doc/manual/source/release-notes/rl-2.34.md 
new/nix-2.34.2/doc/manual/source/release-notes/rl-2.34.md
--- old/nix-2.34.1/doc/manual/source/release-notes/rl-2.34.md   2026-03-08 
11:43:50.000000000 +0100
+++ new/nix-2.34.2/doc/manual/source/release-notes/rl-2.34.md   2026-03-19 
23:47:16.000000000 +0100
@@ -372,3 +372,48 @@
 
 - Improve formatting of error messages and warnings 
[#15397](https://github.com/NixOS/nix/pull/15397)
 
+# Release 2.34.2 (2026-03-20)
+
+## Changes
+
+- Fixed `nix upgrade-nix` without an explicitly specified `--profile` argument 
[#15437](https://github.com/NixOS/nix/issues/15437) 
[#15438](https://github.com/NixOS/nix/pull/15438)
+
+- Erroneous `error (ignored): write of ... bytes: Bad file descriptor` 
warnings on interrupted store copy operations are now fixed 
[#15486](https://github.com/NixOS/nix/pull/15486)
+
+- Reverted changes enabling keep-alive in the HTTP client 
[#15522](https://github.com/NixOS/nix/pull/15522)
+
+  Connection reuse for S3 stores has caused Hydra upload errors due to stale 
connections being closed by the remote servers. Nix currently lacks retry 
mechanisms for 400 `RequestTimeout` errors used by AWS S3.
+
+- Fixed evaluation that accesses the logical store directory using `ssh-ng://` 
`eval-store`s [#15417](https://github.com/NixOS/nix/pull/15417)
+
+  Accessing the logical store directory (typically `/nix/store`) during 
evaluation would fail previously:
+
+  ```
+  nix build nixpkgs#hello --store ssh-ng://host
+  error: path '/nix/store/' is not in the Nix store
+  ```
+
+- S3: restore STS WebIdentity and ECS container credential providers 
[#15507](https://github.com/NixOS/nix/pull/15507)
+
+  Nix 2.33 replaced the S3 backend's `aws-sdk-cpp` credential chain with a
+  custom chain built on `aws-c-auth`. That chain omitted two providers,
+  breaking S3 binary cache access in container workloads:
+
+  - **STS WebIdentity** (`AWS_WEB_IDENTITY_TOKEN_FILE`, `AWS_ROLE_ARN`,
+    `AWS_ROLE_SESSION_NAME`) — used by EKS IRSA, GitHub Actions OIDC, and
+    any `sts:AssumeRoleWithWebIdentity` federation.
+  - **ECS container metadata** (`AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`,
+    `AWS_CONTAINER_CREDENTIALS_FULL_URI`) — used by ECS tasks and EKS Pod
+    Identity.
+
+  The typical symptom was a misleading IMDS error
+  (`Valid credentials could not be sourced by the IMDS provider`), because
+  IMDS is the last provider tried after the correct one was skipped.
+
+  Both providers are now part of the chain, ordered to match the
+  pre-2.33 `DefaultAWSCredentialsProviderChain`:
+  `Environment → SSO → Profile → STS WebIdentity → (ECS | IMDS)`.
+  As in both the old and new AWS SDK default chains, ECS and IMDS are
+  mutually exclusive: when container credential environment variables are
+  set, IMDS is skipped.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nix-2.34.1/src/libcmd/markdown.cc 
new/nix-2.34.2/src/libcmd/markdown.cc
--- old/nix-2.34.1/src/libcmd/markdown.cc       2026-03-08 11:43:50.000000000 
+0100
+++ new/nix-2.34.2/src/libcmd/markdown.cc       2026-03-19 23:47:16.000000000 
+0100
@@ -38,7 +38,9 @@
 #  endif
         .feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | 
LOWDOWN_TABLES,
         .oflags =
-#  if HAVE_LOWDOWN_1_4
+#  if HAVE_LOWDOWN_3
+            LOWDOWN_NORELLINK
+#  elif HAVE_LOWDOWN_1_4
             LOWDOWN_TERM_NORELLINK // To render full links while skipping 
relative ones
 #  else
             LOWDOWN_TERM_NOLINK
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nix-2.34.1/src/libcmd/meson.build 
new/nix-2.34.2/src/libcmd/meson.build
--- old/nix-2.34.1/src/libcmd/meson.build       2026-03-08 11:43:50.000000000 
+0100
+++ new/nix-2.34.2/src/libcmd/meson.build       2026-03-19 23:47:16.000000000 
+0100
@@ -44,6 +44,10 @@
   'HAVE_LOWDOWN_1_4',
   lowdown.version().version_compare('>= 1.4.0').to_int(),
 )
+configdata.set(
+  'HAVE_LOWDOWN_3',
+  lowdown.version().version_compare('>= 3.0.0').to_int(),
+)
 
 readline_flavor = get_option('readline-flavor')
 if readline_flavor == 'editline'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nix-2.34.1/src/libstore/aws-creds.cc 
new/nix-2.34.2/src/libstore/aws-creds.cc
--- old/nix-2.34.1/src/libstore/aws-creds.cc    2026-03-08 11:43:50.000000000 
+0100
+++ new/nix-2.34.2/src/libstore/aws-creds.cc    2026-03-19 23:47:16.000000000 
+0100
@@ -10,7 +10,7 @@
 #  include <aws/crt/auth/Credentials.h>
 #  include <aws/crt/io/Bootstrap.h>
 
-// C library headers for SSO provider support
+// C library headers for SSO, STS WebIdentity, and ECS credential providers
 #  include <aws/auth/credentials.h>
 
 // C library headers for custom logging
@@ -170,6 +170,53 @@
     return createWrappedProvider(aws_credentials_provider_new_sso(allocator, 
&options), allocator);
 }
 
+/**
+ * Create an STS WebIdentity credentials provider using the C library directly.
+ * This reads AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN, AWS_ROLE_SESSION_NAME,
+ * and AWS_REGION from the environment (falling back to the profile config).
+ * Used by EKS IRSA, GitHub Actions OIDC, and other 
sts:AssumeRoleWithWebIdentity flows.
+ * Returns nullptr if the required parameters can't be resolved.
+ */
+static std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider> 
createSTSWebIdentityProvider(
+    const std::string & profileName,
+    Aws::Crt::Io::ClientBootstrap * bootstrap,
+    Aws::Crt::Io::TlsContext * tlsContext,
+    Aws::Crt::Allocator * allocator = Aws::Crt::ApiAllocator())
+{
+    aws_credentials_provider_sts_web_identity_options options;
+    AWS_ZERO_STRUCT(options);
+
+    options.bootstrap = bootstrap->GetUnderlyingHandle();
+    options.tls_ctx = tlsContext ? tlsContext->GetUnderlyingHandle() : nullptr;
+    if (!profileName.empty()) {
+        options.profile_name_override = 
aws_byte_cursor_from_c_str(profileName.c_str());
+    }
+
+    return 
createWrappedProvider(aws_credentials_provider_new_sts_web_identity(allocator, 
&options), allocator);
+}
+
+/**
+ * Create an ECS container credentials provider using the C library directly.
+ * This reads AWS_CONTAINER_CREDENTIALS_RELATIVE_URI or
+ * AWS_CONTAINER_CREDENTIALS_FULL_URI (plus the optional
+ * AWS_CONTAINER_AUTHORIZATION_TOKEN / _TOKEN_FILE) from the environment.
+ * Used by ECS tasks and EKS Pod Identity.
+ * Returns nullptr if neither URI env var is set.
+ */
+static std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider> createECSProvider(
+    Aws::Crt::Io::ClientBootstrap * bootstrap,
+    Aws::Crt::Io::TlsContext * tlsContext,
+    Aws::Crt::Allocator * allocator = Aws::Crt::ApiAllocator())
+{
+    aws_credentials_provider_ecs_environment_options options;
+    AWS_ZERO_STRUCT(options);
+
+    options.bootstrap = bootstrap->GetUnderlyingHandle();
+    options.tls_ctx = tlsContext ? tlsContext->GetUnderlyingHandle() : nullptr;
+
+    return 
createWrappedProvider(aws_credentials_provider_new_ecs_from_environment(allocator,
 &options), allocator);
+}
+
 static AwsCredentials 
getCredentialsFromProvider(std::shared_ptr<Aws::Crt::Auth::ICredentialsProvider>
 provider)
 {
     if (!provider || !provider->IsValid()) {
@@ -223,13 +270,14 @@
         // This ensures AWS logs respect Nix's verbosity settings and are 
formatted consistently.
         initialiseAwsLogger();
 
-        // Create a shared TLS context for SSO (required for HTTPS connections)
+        // Create a shared TLS context for SSO, STS WebIdentity, and ECS 
providers (required for HTTPS)
         auto allocator = Aws::Crt::ApiAllocator();
         auto tlsCtxOptions = 
Aws::Crt::Io::TlsContextOptions::InitDefaultClient(allocator);
         tlsContext =
             std::make_shared<Aws::Crt::Io::TlsContext>(tlsCtxOptions, 
Aws::Crt::Io::TlsMode::CLIENT, allocator);
         if (!tlsContext || !*tlsContext) {
-            warn("failed to create TLS context for AWS SSO; SSO authentication 
will be unavailable");
+            warn(
+                "failed to create TLS context for AWS credential providers; 
SSO, STS WebIdentity, and ECS container authentication will be unavailable");
             tlsContext = nullptr;
         }
 
@@ -273,19 +321,20 @@
 
     debug("[pid=%d] creating new AWS credential provider for profile '%s'", 
getpid(), profileDisplayName);
 
-    // Build a custom credential chain: Environment → SSO → Profile → IMDS
+    // Build a custom credential chain: Environment → SSO → Profile → STS 
WebIdentity → ECS → IMDS
     // This works for both default and named profiles, ensuring consistent 
behavior
     // including SSO support and proper TLS context for STS-based role 
assumption.
     Aws::Crt::Auth::CredentialsProviderChainConfig chainConfig;
     auto allocator = Aws::Crt::ApiAllocator();
 
-    auto addProviderToChain = [&](std::string_view name, auto createProvider) {
+    auto addProviderToChain = [&](std::string_view name, auto createProvider) 
-> bool {
         if (auto provider = createProvider()) {
             chainConfig.Providers.push_back(provider);
             debug("Added AWS %s Credential Provider to chain for profile 
'%s'", name, profileDisplayName);
-        } else {
-            debug("Skipped AWS %s Credential Provider for profile '%s'", name, 
profileDisplayName);
+            return true;
         }
+        debug("Skipped AWS %s Credential Provider for profile '%s'", name, 
profileDisplayName);
+        return false;
     };
 
     // 1. Environment variables (highest priority)
@@ -311,12 +360,37 @@
         return 
Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderProfile(profileConfig,
 allocator);
     });
 
-    // 4. IMDS provider (for EC2 instances, lowest priority)
-    addProviderToChain("IMDS", [&]() {
-        Aws::Crt::Auth::CredentialsProviderImdsConfig imdsConfig;
-        imdsConfig.Bootstrap = bootstrap;
-        return 
Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderImds(imdsConfig, 
allocator);
-    });
+    // 4. STS WebIdentity (AWS_WEB_IDENTITY_TOKEN_FILE + AWS_ROLE_ARN — EKS 
IRSA, GitHub Actions OIDC)
+    // 5. ECS container metadata (AWS_CONTAINER_CREDENTIALS_RELATIVE_URI — ECS 
tasks, EKS Pod Identity)
+    // ECS and IMDS are mutually exclusive per both the aws-c-auth default 
chain and the
+    // pre-2.33 aws-sdk-cpp DefaultAWSCredentialsProviderChain: when container 
credential
+    // env vars are set, IMDS is skipped so a transient ECS endpoint failure 
can't silently
+    // fall through to the (typically broader) EC2 instance profile.
+    bool ecsAdded = false;
+    if (tlsContext) {
+        addProviderToChain("STS WebIdentity", [&]() {
+            return createSTSWebIdentityProvider(profile, bootstrap, 
tlsContext.get(), allocator);
+        });
+        ecsAdded =
+            addProviderToChain("ECS", [&]() { return 
createECSProvider(bootstrap, tlsContext.get(), allocator); });
+    } else {
+        debug(
+            "Skipped AWS STS WebIdentity and ECS Credential Providers for 
profile '%s': TLS context unavailable",
+            profileDisplayName);
+    }
+
+    // 6. IMDS provider (for EC2 instances, lowest priority) — only if ECS 
didn't claim the slot
+    if (!ecsAdded) {
+        addProviderToChain("IMDS", [&]() {
+            Aws::Crt::Auth::CredentialsProviderImdsConfig imdsConfig;
+            imdsConfig.Bootstrap = bootstrap;
+            return 
Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderImds(imdsConfig, 
allocator);
+        });
+    } else {
+        debug(
+            "Skipped AWS IMDS Credential Provider for profile '%s': ECS 
provider is active (mutually exclusive)",
+            profileDisplayName);
+    }
 
     return 
Aws::Crt::Auth::CredentialsProvider::CreateCredentialsProviderChain(chainConfig,
 allocator);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nix-2.34.1/src/libstore/filetransfer.cc 
new/nix-2.34.2/src/libstore/filetransfer.cc
--- old/nix-2.34.1/src/libstore/filetransfer.cc 2026-03-08 11:43:50.000000000 
+0100
+++ new/nix-2.34.2/src/libstore/filetransfer.cc 2026-03-19 23:47:16.000000000 
+0100
@@ -558,12 +558,6 @@
 #endif
             curl_easy_setopt(req, CURLOPT_CONNECTTIMEOUT, 
fileTransfer.settings.connectTimeout.get());
 
-            // Enable TCP keep-alive so that idle connections in curl's reuse 
pool
-            // are not silently dropped by NATs, firewalls, or load balancers.
-            curl_easy_setopt(req, CURLOPT_TCP_KEEPALIVE, 1L);
-            curl_easy_setopt(req, CURLOPT_TCP_KEEPIDLE, 60L);
-            curl_easy_setopt(req, CURLOPT_TCP_KEEPINTVL, 60L);
-
             curl_easy_setopt(req, CURLOPT_LOW_SPEED_LIMIT, 1L);
             curl_easy_setopt(req, CURLOPT_LOW_SPEED_TIME, 
fileTransfer.settings.stalledDownloadTimeout.get());
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nix-2.34.1/src/libstore/remote-fs-accessor.cc 
new/nix-2.34.2/src/libstore/remote-fs-accessor.cc
--- old/nix-2.34.1/src/libstore/remote-fs-accessor.cc   2026-03-08 
11:43:50.000000000 +0100
+++ new/nix-2.34.2/src/libstore/remote-fs-accessor.cc   2026-03-19 
23:47:16.000000000 +0100
@@ -35,6 +35,8 @@
 
 std::optional<SourceAccessor::Stat> RemoteFSAccessor::maybeLstat(const 
CanonPath & path)
 {
+    if (path.isRoot())
+        return Stat{.type = tDirectory};
     auto res = fetch(path);
     return res.first->maybeLstat(res.second);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nix-2.34.1/src/libutil/fs-sink.cc 
new/nix-2.34.2/src/libutil/fs-sink.cc
--- old/nix-2.34.1/src/libutil/fs-sink.cc       2026-03-08 11:43:50.000000000 
+0100
+++ new/nix-2.34.2/src/libutil/fs-sink.cc       2026-03-19 23:47:16.000000000 
+0100
@@ -148,6 +148,16 @@
 
     ~RestoreRegularFile()
     {
+        /* Flush the sink before FdSink destructor has a chance to run and 
we've
+           closed the file descriptor. */
+        if (fd) {
+            try {
+                FdSink::flush();
+            } catch (...) {
+                ignoreExceptionInDestructor();
+            }
+        }
+
         /* Initiate an fsync operation without waiting for the
            result. The real fsync should be run before registering a
            store path, but this is a performance optimization to allow
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nix-2.34.1/src/nix/upgrade-nix.cc 
new/nix-2.34.2/src/nix/upgrade-nix.cc
--- old/nix-2.34.1/src/nix/upgrade-nix.cc       2026-03-08 11:43:50.000000000 
+0100
+++ new/nix-2.34.2/src/nix/upgrade-nix.cc       2026-03-19 23:47:16.000000000 
+0100
@@ -16,6 +16,14 @@
 using namespace nix;
 
 /**
+ * Check whether a path has a "profiles" component.
+ */
+static bool hasProfilesComponent(const std::filesystem::path & path)
+{
+    return std::ranges::contains(path, OS_STR("profiles"));
+}
+
+/**
  * Settings related to upgrading Nix itself.
  */
 struct UpgradeSettings : Config
@@ -157,14 +165,13 @@
 
         auto profileDir = where.parent_path();
 
-        // Resolve profile to /nix/var/nix/profiles/<name> link.
-        while (canonPath(profileDir).string().find("/profiles/") == 
std::string::npos
-               && std::filesystem::is_symlink(profileDir))
-            profileDir = readLink(profileDir);
-
-        printInfo("found profile %s", PathFmt(profileDir));
-
-        auto userEnv = canonPath(profileDir);
+        // Chase symlinks until we find a path under a "profiles"
+        // directory, or we run out of symlinks.
+        auto resolved = profileDir;
+        while (!hasProfilesComponent(canonPath(resolved)) && 
std::filesystem::is_symlink(resolved))
+            // Note that operator/ replaces lhs when rhs is absolute.
+            resolved = resolved.parent_path() / readLink(resolved);
+        printInfo("found profile %s", PathFmt(resolved));
 
         if (std::filesystem::exists(profileDir / "manifest.json"))
             throw Error(
@@ -174,8 +181,10 @@
         if (!std::filesystem::exists(profileDir / "manifest.nix"))
             throw Error("directory %s does not appear to be part of a Nix 
profile", PathFmt(profileDir));
 
-        if (!store->isValidPath(store->parseStorePath(userEnv.string())))
-            throw Error("directory %s is not in the Nix store", 
PathFmt(userEnv));
+        auto userEnv = store->followLinksToStorePath(profileDir.string());
+
+        if (!store->isValidPath(userEnv))
+            throw Error("directory %s is not in the Nix store", 
PathFmt(profileDir));
 
         return profileDir;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nix-2.34.1/tests/nixos/default.nix 
new/nix-2.34.2/tests/nixos/default.nix
--- old/nix-2.34.1/tests/nixos/default.nix      2026-03-08 11:43:50.000000000 
+0100
+++ new/nix-2.34.2/tests/nixos/default.nix      2026-03-19 23:47:16.000000000 
+0100
@@ -205,4 +205,21 @@
   fetchersSubstitute = runNixOSTest ./fetchers-substitute.nix;
 
   chrootStore = runNixOSTest ./chroot-store.nix;
+
+  upgrade-nix = runNixOSTest {
+    imports = [ ./upgrade-nix.nix ];
+    upgrade-nix.oldNix = nixComponents.nix-cli;
+  };
+
+  upgrade-nix_fromStable = runNixOSTest {
+    imports = [ ./upgrade-nix.nix ];
+    name = lib.mkForce "upgrade-nix-from-stable";
+    upgrade-nix.oldNix = pkgs.nixVersions.stable;
+  };
+
+  upgrade-nix_fromLatest = runNixOSTest {
+    imports = [ ./upgrade-nix.nix ];
+    name = lib.mkForce "upgrade-nix-from-latest";
+    upgrade-nix.oldNix = pkgs.nixVersions.latest;
+  };
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nix-2.34.1/tests/nixos/upgrade-nix.nix 
new/nix-2.34.2/tests/nixos/upgrade-nix.nix
--- old/nix-2.34.1/tests/nixos/upgrade-nix.nix  1970-01-01 01:00:00.000000000 
+0100
+++ new/nix-2.34.2/tests/nixos/upgrade-nix.nix  2026-03-19 23:47:16.000000000 
+0100
@@ -0,0 +1,104 @@
+# This installs an older Nix into a nix-env profile, and then runs `nix 
upgrade-nix`
+# pointing at a local fallback-paths file containing the locally built nix.
+#
+# This is based on nixpkgs' nixosTests.nix-upgrade test.
+# See 
https://github.com/NixOS/nixpkgs/blob/e3469a82fbd496d9c8e6192bbaf7cf056c6449ff/nixos/tests/nix/upgrade.nix.
+
+{
+  config,
+  lib,
+  nixComponents,
+  system,
+  ...
+}:
+let
+  pkgs = config.nodes.machine.nixpkgs.pkgs;
+
+  newNix = nixComponents.nix-cli;
+  oldNix = config.upgrade-nix.oldNix;
+
+  fallback-paths = pkgs.writeTextDir "fallback-paths.nix" ''
+    {
+      ${system} = "${newNix}";
+    }
+  '';
+in
+{
+  options.upgrade-nix.oldNix = lib.mkOption {
+    type = lib.types.package;
+    default = newNix;
+    description = "The Nix package to install before upgrading.";
+  };
+
+  config = {
+    name = "upgrade-nix";
+
+    nodes.machine =
+      { lib, ... }:
+      {
+        virtualisation.writableStore = true;
+        nix.settings.substituters = lib.mkForce [ ];
+        nix.settings.hashed-mirrors = null;
+        nix.settings.connect-timeout = 1;
+        nix.extraOptions = "experimental-features = nix-command";
+        environment.localBinInPath = true;
+        system.extraDependencies = [
+          fallback-paths
+          newNix
+          oldNix
+        ];
+        users.users.alice = {
+          isNormalUser = true;
+          packages = [ newNix ];
+        };
+      };
+
+    testScript = /* py */ ''
+      machine.start()
+      machine.wait_for_unit("multi-user.target")
+
+      with subtest("nix-current"):
+          # Create a profile to pretend we are on non-NixOS
+
+          print(machine.succeed("nix --version"))
+          machine.succeed("nix-env -i ${oldNix} -p /root/.local")
+          result = machine.succeed("/root/.local/bin/nix --version")
+          print(f"installed: {result}")
+
+      with subtest("nix-upgrade"):
+          machine.succeed(
+              "nix upgrade-nix"
+              " --nix-store-paths-url 
file://${fallback-paths}/fallback-paths.nix"
+              " --profile /root/.local"
+          )
+          result = machine.succeed("/root/.local/bin/nix --version")
+          print(f"after upgrade: {result}")
+          assert "${newNix.version}" in result, \
+              f"expected ${newNix.version} in: {result}"
+
+      with subtest("nix-build-with-mismatched-daemon"):
+          # The daemon is still running oldNix; verify the new client works.
+          machine.succeed(
+              "runuser -u alice -- nix build"
+              " --expr 'derivation { name = \"test\"; system = \"${system}\";"
+              " builder = \"/bin/sh\"; args = [\"-c\" \"echo test > $out\"]; 
}'"
+              " --print-out-paths"
+          )
+
+      with subtest("nix-upgrade-auto-detect"):
+          # Without passing in --profile, getProfileDir auto-detects the 
profile
+          # by finding nix-env in PATH and resolving the symlink chain back
+          # to the store.
+          machine.succeed("nix-env -i ${oldNix} -p /root/.local")
+          machine.succeed(
+              "PATH=/root/.local/bin:$PATH"
+              " ${newNix}/bin/nix upgrade-nix"
+              " --nix-store-paths-url 
file://${fallback-paths}/fallback-paths.nix"
+          )
+          result = machine.succeed("/root/.local/bin/nix --version")
+          print(f"after auto-detect upgrade: {result}")
+          assert "${newNix.version}" in result, \
+              f"expected ${newNix.version} in: {result}"
+    '';
+  };
+}

Reply via email to