mirror of
https://github.com/NixOS/nix
synced 2025-06-25 14:51:16 +02:00
fix: Handle symlinks and FIFOs in nix hash
where possible
Fixes https://github.com/NixOS/nix/issues/11756 Fixes https://github.com/NixOS/nix/issues/11681
This commit is contained in:
parent
69853c067c
commit
36563c69a4
3 changed files with 45 additions and 4 deletions
|
@ -43,7 +43,7 @@ struct PosixSourceAccessor : virtual SourceAccessor
|
||||||
std::optional<std::filesystem::path> getPhysicalPath(const CanonPath & path) override;
|
std::optional<std::filesystem::path> getPhysicalPath(const CanonPath & path) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a `PosixSourceAccessor` and `CanonPath` corresponding to
|
* Create a `PosixSourceAccessor` and `SourcePath` corresponding to
|
||||||
* some native path.
|
* some native path.
|
||||||
*
|
*
|
||||||
* The `PosixSourceAccessor` is rooted as far up the tree as
|
* The `PosixSourceAccessor` is rooted as far up the tree as
|
||||||
|
|
|
@ -87,18 +87,35 @@ struct CmdHashBase : Command
|
||||||
return std::make_unique<HashSink>(hashAlgo);
|
return std::make_unique<HashSink>(hashAlgo);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto path2 = PosixSourceAccessor::createAtRoot(path);
|
auto makeSourcePath = [&]() -> SourcePath {
|
||||||
|
return PosixSourceAccessor::createAtRoot(makeParentCanonical(path));
|
||||||
|
};
|
||||||
|
|
||||||
Hash h { HashAlgorithm::SHA256 }; // throwaway def to appease C++
|
Hash h { HashAlgorithm::SHA256 }; // throwaway def to appease C++
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FileIngestionMethod::Flat:
|
case FileIngestionMethod::Flat:
|
||||||
|
{
|
||||||
|
// While usually we could use the some code as for NixArchive,
|
||||||
|
// the Flat method needs to support FIFOs, such as those
|
||||||
|
// produced by bash process substitution, e.g.:
|
||||||
|
// nix hash --mode flat <(echo hi)
|
||||||
|
// Also symlinks semantics are unambiguous in the flat case,
|
||||||
|
// so we don't need to go low-level, or reject symlink `path`s.
|
||||||
|
auto hashSink = makeSink();
|
||||||
|
readFile(path, *hashSink);
|
||||||
|
h = hashSink->finish().first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case FileIngestionMethod::NixArchive:
|
case FileIngestionMethod::NixArchive:
|
||||||
{
|
{
|
||||||
|
auto sourcePath = makeSourcePath();
|
||||||
auto hashSink = makeSink();
|
auto hashSink = makeSink();
|
||||||
dumpPath(path2, *hashSink, (FileSerialisationMethod) mode);
|
dumpPath(sourcePath, *hashSink, (FileSerialisationMethod) mode);
|
||||||
h = hashSink->finish().first;
|
h = hashSink->finish().first;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FileIngestionMethod::Git: {
|
case FileIngestionMethod::Git: {
|
||||||
|
auto sourcePath = makeSourcePath();
|
||||||
std::function<git::DumpHook> hook;
|
std::function<git::DumpHook> hook;
|
||||||
hook = [&](const SourcePath & path) -> git::TreeEntry {
|
hook = [&](const SourcePath & path) -> git::TreeEntry {
|
||||||
auto hashSink = makeSink();
|
auto hashSink = makeSink();
|
||||||
|
@ -109,7 +126,7 @@ struct CmdHashBase : Command
|
||||||
.hash = hash,
|
.hash = hash,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
h = hook(path2).hash;
|
h = hook(sourcePath).hash;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,3 +92,27 @@ try2 md5 "20f3ffe011d4cfa7d72bfabef7882836"
|
||||||
rm "$TEST_ROOT/hash-path/hello"
|
rm "$TEST_ROOT/hash-path/hello"
|
||||||
ln -s x "$TEST_ROOT/hash-path/hello"
|
ln -s x "$TEST_ROOT/hash-path/hello"
|
||||||
try2 md5 "f78b733a68f5edbdf9413899339eaa4a"
|
try2 md5 "f78b733a68f5edbdf9413899339eaa4a"
|
||||||
|
|
||||||
|
# Flat mode supports process substitution
|
||||||
|
h=$(nix hash path --mode flat --type sha256 --base32 <(printf "SMASH THE STATE"))
|
||||||
|
[[ 0d9n3r2i4m1zgy0wpqbsyabsfzgs952066bfp8gwvcg4mkr4r5g8 == "$h" ]]
|
||||||
|
|
||||||
|
# Flat mode supports process substitution (hash file)
|
||||||
|
h=$(nix hash file --type sha256 --base32 <(printf "SMASH THE STATE"))
|
||||||
|
[[ 0d9n3r2i4m1zgy0wpqbsyabsfzgs952066bfp8gwvcg4mkr4r5g8 == "$h" ]]
|
||||||
|
|
||||||
|
# Symlinks in the ancestry are ok and don't affect the result
|
||||||
|
mkdir -p "$TEST_ROOT/simple" "$TEST_ROOT/try/to/mess/with/it"
|
||||||
|
echo hi > "$TEST_ROOT/simple/hi"
|
||||||
|
ln -s "$TEST_ROOT/simple" "$TEST_ROOT/try/to/mess/with/it/simple-link"
|
||||||
|
h=$(nix hash path --type sha256 --base32 "$TEST_ROOT/simple/hi")
|
||||||
|
[[ 1xmr8jicvzszfzpz46g37mlpvbzjl2wpwvl2b05psipssyp1sm8h == "$h" ]]
|
||||||
|
h=$(nix hash path --type sha256 --base32 "$TEST_ROOT/try/to/mess/with/it/simple-link/hi")
|
||||||
|
[[ 1xmr8jicvzszfzpz46g37mlpvbzjl2wpwvl2b05psipssyp1sm8h == "$h" ]]
|
||||||
|
|
||||||
|
# nix hash --mode nar does not canonicalize a symlink argument.
|
||||||
|
# Otherwise it can't generate a NAR whose root is a symlink.
|
||||||
|
# If you want to follow the symlink, pass $(realpath -s ...) instead.
|
||||||
|
ln -s /non-existent-48cujwe8ndf4as0bne "$TEST_ROOT/symlink-to-nowhere"
|
||||||
|
h=$(nix hash path --mode nar --type sha256 --base32 "$TEST_ROOT/symlink-to-nowhere")
|
||||||
|
[[ 1bl5ry3x1fcbwgr5c2x50bn572iixh4j1p6ax5isxly2ddgn8pbp == "$h" ]] # manually verified hash
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue