Skip to content

Commit 5175e8a

Browse files
authored
Merge pull request #1647 from obsidiansystems/prepare-for-queue-runner-redirected-store
Prepare for queue runner redirected store
2 parents f1e4995 + 277a519 commit 5175e8a

6 files changed

Lines changed: 48 additions & 6 deletions

File tree

subprojects/crates/nix-utils/include/nix.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ void nar_from_path(const StoreWrapper &src_store, rust::Str path,
7070
rust::String list_nar_deep(const StoreWrapper &wrapper, rust::Str path);
7171

7272
void ensure_path(const StoreWrapper &wrapper, rust::Str path);
73+
rust::String to_real_path(const StoreWrapper &wrapper, rust::Str path);
7374
rust::String write_derivation(const StoreWrapper &wrapper, rust::Str json);
7475
rust::Vec<DerivationHash> static_output_hashes(const StoreWrapper &wrapper,
7576
rust::Str output_path);

subprojects/crates/nix-utils/src/drv.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ pub async fn query_drv(
3434
return Ok(None);
3535
}
3636

37-
let full_path = store.print_store_path(drv);
38-
if !fs_err::tokio::try_exists(&full_path).await? {
37+
if !store.is_valid_path(drv).await {
3938
return Ok(None);
4039
}
4140

42-
let input = fs_err::tokio::read_to_string(&full_path).await?;
41+
let real_path = store.to_real_path(drv).await?;
42+
let input = fs_err::tokio::read_to_string(&real_path).await?;
4343
Ok(Some(parse_drv(store.get_store_dir(), drv, &input)?))
4444
}
4545

subprojects/crates/nix-utils/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ mod ffi {
213213
fn list_nar_deep(store: &StoreWrapper, path: &str) -> Result<String>;
214214

215215
fn ensure_path(store: &StoreWrapper, path: &str) -> Result<()>;
216+
fn to_real_path(store: &StoreWrapper, path: &str) -> Result<String>;
216217
fn write_derivation(store: &StoreWrapper, json: &str) -> Result<String>;
217218
fn static_output_hashes(
218219
store: &StoreWrapper,
@@ -883,6 +884,17 @@ impl LocalStore {
883884
})
884885
.await
885886
}
887+
888+
/// Resolve a store path to its physical filesystem location.
889+
///
890+
/// For stores where the physical store directory differs from the
891+
/// logical `storeDir` (e.g. `local?root=X&store=Y`), this returns the
892+
/// actual on-disk path rather than the logical store path.
893+
pub async fn to_real_path(&self, path: &StorePath) -> Result<String, Error> {
894+
let printed = self.base.store_dir.display(path).to_string();
895+
let store = self.base.wrapper.clone();
896+
asyncify(move || ffi::to_real_path(store.as_raw(), &printed)).await
897+
}
886898
}
887899

888900
impl BaseStore for LocalStore {

subprojects/crates/nix-utils/src/nix.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <string.h>
77

88
#include <nix/store/derivations.hh>
9+
#include <nix/store/local-fs-store.hh>
910
#include <nix/store/remote-store.hh>
1011
#include <nix/store/store-api.hh>
1112
#include <nix/store/store-open.hh>
@@ -324,6 +325,19 @@ void ensure_path(const StoreWrapper &wrapper, rust::Str path) {
324325
store->ensurePath(store->followLinksToStorePath(AS_VIEW(path)));
325326
}
326327

328+
rust::String to_real_path(const StoreWrapper &wrapper, rust::Str path) {
329+
auto store = wrapper._store;
330+
auto *lfs = dynamic_cast<nix::LocalFSStore *>(&*store);
331+
if (!lfs) {
332+
throw nix::Error(
333+
"toRealPath: store '%s' is not a local filesystem store",
334+
store->config.getHumanReadableURI());
335+
}
336+
auto storePath = store->parseStorePath(AS_VIEW(path));
337+
auto s = lfs->toRealPath(storePath).string();
338+
return rust::String(s.data(), s.size());
339+
}
340+
327341
rust::String write_derivation(const StoreWrapper &wrapper, rust::Str json) {
328342
auto store = wrapper._store;
329343
auto drv = nix::Derivation::parseJsonAndValidate(

subprojects/hydra/lib/Hydra/Helper/Nix.pm

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,17 @@ sub gcRootFor {
141141
sub registerRoot {
142142
my ($path) = @_;
143143
my $link = gcRootFor $path;
144-
return if -e $link;
144+
# A pre-existing symlink (e.g. from nix-eval-jobs --gc-roots-dir) may
145+
# point at a logical store path whose physical location is elsewhere,
146+
# so `-e` would return false even though the target is a valid store
147+
# object. Read the symlink and ask the store whether the target is
148+
# valid, rather than testing the path on this filesystem.
149+
if (-l $link) {
150+
my $target = readlink $link;
151+
return if defined $target && $MACHINE_LOCAL_STORE->isValidPath($target);
152+
# Stale symlink: remove it so we can replace it below.
153+
unlink $link;
154+
}
145155
open(my $root, ">", $link) or die "cannot create GC root `$link' to `$path'";
146156
close $root;
147157
}

subprojects/hydra/script/hydra-eval-jobset

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,13 @@ sub checkJobsetWrapped {
665665
die "multiple alternatives for the input containing the declarative project specification are not supported\n"
666666
if scalar @declInputs != 1;
667667
my $declFile = $declInput->{storePath} . "/" . $project->declfile;
668-
my $declText = read_text($declFile)
669-
or die "Couldn't read declarative specification file $declFile: $!\n";
668+
# Use `nix store cat` so the physical store location is resolved
669+
# by the store itself (handles root= stores where physical != logical).
670+
my ($res, $declText, $catErr) = captureStdoutStderr(
671+
60,
672+
"nix", "--extra-experimental-features", "nix-command",
673+
"store", "cat", $declFile);
674+
die "Couldn't read declarative specification file $declFile: $catErr\n" if $res != 0;
670675
my $declSpec;
671676
eval {
672677
$declSpec = decode_json($declText);

0 commit comments

Comments
 (0)