RestoreSink::createDirectory(): Use append()

On macOS, `mkdir("x/')` behaves differently than `mkdir("x")` if `x` is
a dangling symlink (the formed succeed while the latter fails). So make
sure we always strip the trailing slash.
This commit is contained in:
Eelco Dolstra 2024-09-05 22:21:53 +02:00
parent 21dcbd7e83
commit 9fcb588dd8
2 changed files with 14 additions and 14 deletions

View file

@ -68,11 +68,19 @@ static RestoreSinkSettings restoreSinkSettings;
static GlobalConfig::Register r1(&restoreSinkSettings); static GlobalConfig::Register r1(&restoreSinkSettings);
static std::filesystem::path append(const std::filesystem::path & src, const CanonPath & path)
{
auto dst = src;
if (!path.rel().empty())
dst /= path.rel();
return dst;
}
void RestoreSink::createDirectory(const CanonPath & path) void RestoreSink::createDirectory(const CanonPath & path)
{ {
if (!std::filesystem::create_directory(dstPath / path.rel())) auto p = append(dstPath, path);
throw Error("path '%s' already exists", (dstPath / path.rel()).string()); if (!std::filesystem::create_directory(p))
throw Error("path '%s' already exists", p.string());
}; };
struct RestoreRegularFile : CreateRegularFileSink { struct RestoreRegularFile : CreateRegularFileSink {
@ -94,14 +102,6 @@ struct RestoreRegularFile : CreateRegularFileSink {
void preallocateContents(uint64_t size) override; void preallocateContents(uint64_t size) override;
}; };
static std::filesystem::path append(const std::filesystem::path & src, const CanonPath & path)
{
auto dst = src;
if (!path.rel().empty())
dst /= path.rel();
return dst;
}
void RestoreSink::createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> func) void RestoreSink::createRegularFile(const CanonPath & path, std::function<void(CreateRegularFileSink &)> func)
{ {
auto p = append(dstPath, path); auto p = append(dstPath, path);

View file

@ -11,18 +11,18 @@ rm -rf "$TEST_ROOT/out"
expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "NAR directory is not sorted" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "NAR directory is not sorted"
# Check that nix-store --restore fails if the output already exists. # Check that nix-store --restore fails if the output already exists.
expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out/' already exists" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out' already exists"
rm -rf "$TEST_ROOT/out" rm -rf "$TEST_ROOT/out"
echo foo > "$TEST_ROOT/out" echo foo > "$TEST_ROOT/out"
expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "cannot create directory.*File exists" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "File exists"
rm -rf "$TEST_ROOT/out" rm -rf "$TEST_ROOT/out"
ln -s "$TEST_ROOT/out2" "$TEST_ROOT/out" ln -s "$TEST_ROOT/out2" "$TEST_ROOT/out"
expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "cannot create directory.*File exists" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "File exists"
mkdir -p "$TEST_ROOT/out2" mkdir -p "$TEST_ROOT/out2"
expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out/' already exists" expectStderr 1 nix-store --restore "$TEST_ROOT/out" < duplicate.nar | grepQuiet "path '.*/out' already exists"
# Check whether restoring and dumping a NAR that contains case # Check whether restoring and dumping a NAR that contains case
# collisions is round-tripping, even on a case-insensitive system. # collisions is round-tripping, even on a case-insensitive system.