mirror of
https://github.com/NixOS/nix.git
synced 2024-11-22 06:42:28 +00:00
followSymlinks: Improve error message
This commit is contained in:
parent
2fc6d09c71
commit
5e3799bb69
3
.gitignore
vendored
3
.gitignore
vendored
@ -43,6 +43,9 @@ perl/Makefile.config
|
||||
/src/libexpr/nix.tbl
|
||||
/src/libexpr/tests/libnixexpr-tests
|
||||
|
||||
# /src/libfetchers
|
||||
/src/libfetchers/tests/libnixfetchers-tests
|
||||
|
||||
# /src/libstore/
|
||||
*.gen.*
|
||||
/src/libstore/tests/libnixstore-tests
|
||||
|
1
Makefile
1
Makefile
@ -29,6 +29,7 @@ UNIT_TEST_ENV = _NIX_TEST_UNIT_DATA=unit-test-data
|
||||
makefiles += \
|
||||
src/libutil/tests/local.mk \
|
||||
src/libstore/tests/local.mk \
|
||||
src/libfetchers/tests/local.mk \
|
||||
src/libexpr/tests/local.mk
|
||||
endif
|
||||
|
||||
|
@ -70,7 +70,7 @@ SourcePath SourcePath::followSymlinks() const {
|
||||
while (true) {
|
||||
// Basic cycle/depth limit to avoid infinite loops.
|
||||
if (++followCount >= maxFollow)
|
||||
throw Error("too many symbolic links encountered while traversing the path '%s'", path);
|
||||
throw Error("too many levels of symbolic links while traversing the path '%s'; assuming it leads to a cycle after following %d indirections", this->to_string(), maxFollow);
|
||||
if (path.lstat().type != InputAccessor::tSymlink) break;
|
||||
path = {path.accessor, CanonPath(path.readLink(), path.path.parent().value_or(CanonPath::root))};
|
||||
}
|
||||
|
@ -12,6 +12,14 @@ struct MemoryInputAccessorImpl : MemoryInputAccessor, MemorySourceAccessor
|
||||
MemorySourceAccessor::addFile(path, std::move(contents))
|
||||
};
|
||||
}
|
||||
|
||||
SourcePath addSymlink(CanonPath path, std::string && contents) override
|
||||
{
|
||||
return {
|
||||
ref(shared_from_this()),
|
||||
MemorySourceAccessor::addSymlink(path, std::move(contents))
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
ref<MemoryInputAccessor> makeMemoryInputAccessor()
|
||||
|
@ -8,6 +8,7 @@ namespace nix {
|
||||
struct MemoryInputAccessor : InputAccessor
|
||||
{
|
||||
virtual SourcePath addFile(CanonPath path, std::string && contents) = 0;
|
||||
virtual SourcePath addSymlink(CanonPath path, std::string && contents) = 0;
|
||||
};
|
||||
|
||||
ref<MemoryInputAccessor> makeMemoryInputAccessor();
|
||||
|
29
src/libfetchers/tests/input-accessor.cc
Normal file
29
src/libfetchers/tests/input-accessor.cc
Normal file
@ -0,0 +1,29 @@
|
||||
#include "../input-accessor.hh"
|
||||
#include "../memory-input-accessor.hh"
|
||||
#include "gmock/gmock.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include "terminal.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
TEST(SourcePath, followSymlinks_cycle) {
|
||||
auto fs = makeMemoryInputAccessor();
|
||||
fs->addSymlink({"origin", CanonPath::root}, "a");
|
||||
fs->addSymlink({"a", CanonPath::root}, "b");
|
||||
fs->addSymlink({"b", CanonPath::root}, "a");
|
||||
|
||||
ASSERT_TRUE(fs->pathExists({"a", CanonPath::root}));
|
||||
SourcePath origin (fs->root() + "origin");
|
||||
try {
|
||||
origin.followSymlinks();
|
||||
ASSERT_TRUE(false);
|
||||
} catch (const Error &e) {
|
||||
auto msg = filterANSIEscapes(e.what(), true);
|
||||
// EXPECT_THAT(msg, ("too many levels of symbolic links"));
|
||||
EXPECT_THAT(msg, testing::HasSubstr("too many levels of symbolic links"));
|
||||
EXPECT_THAT(msg, testing::HasSubstr("'/origin'"));
|
||||
EXPECT_THAT(msg, testing::HasSubstr("assuming it leads to a cycle after following 1000 indirections"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
39
src/libfetchers/tests/local.mk
Normal file
39
src/libfetchers/tests/local.mk
Normal file
@ -0,0 +1,39 @@
|
||||
check: libfetchers-tests-exe_RUN
|
||||
|
||||
programs += libfetchers-tests-exe
|
||||
|
||||
libfetchers-tests-exe_NAME = libnixfetchers-tests
|
||||
|
||||
libfetchers-tests-exe_DIR := $(d)
|
||||
|
||||
ifeq ($(INSTALL_UNIT_TESTS), yes)
|
||||
libfetchers-tests-exe_INSTALL_DIR := $(checkbindir)
|
||||
else
|
||||
libfetchers-tests-exe_INSTALL_DIR :=
|
||||
endif
|
||||
|
||||
|
||||
libfetchers-tests-exe_LIBS = libfetchers-tests libstore
|
||||
|
||||
|
||||
libfetchers-tests-exe_LDFLAGS := $(GTEST_LIBS)
|
||||
|
||||
libraries += libfetchers-tests
|
||||
|
||||
libfetchers-tests_NAME = libnixfetchers-tests
|
||||
|
||||
libfetchers-tests_DIR := $(d)
|
||||
|
||||
ifeq ($(INSTALL_UNIT_TESTS), yes)
|
||||
libfetchers-tests_INSTALL_DIR := $(checklibdir)
|
||||
else
|
||||
libfetchers-tests_INSTALL_DIR :=
|
||||
endif
|
||||
|
||||
libfetchers-tests_SOURCES := $(wildcard $(d)/*.cc)
|
||||
|
||||
libfetchers-tests_CXXFLAGS += -I src/libfetchers -I src/libutil -I src/libstore
|
||||
|
||||
libfetchers-tests_LIBS = libutil-tests libstore-tests libutil libstore libfetchers
|
||||
|
||||
libfetchers-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)
|
@ -121,6 +121,19 @@ CanonPath MemorySourceAccessor::addFile(CanonPath path, std::string && contents)
|
||||
return path;
|
||||
}
|
||||
|
||||
CanonPath MemorySourceAccessor::addSymlink(CanonPath path, std::string &&contents)
|
||||
{
|
||||
auto * f = open(path, File { File::Symlink {} });
|
||||
if (!f)
|
||||
throw Error("file '%s' cannot be made because some parent file is not a directory", path);
|
||||
if (auto * s = std::get_if<File::Symlink>(&f->raw))
|
||||
s->target = std::move(contents);
|
||||
else
|
||||
throw Error("file '%s' is not a symbolic link", path);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
using File = MemorySourceAccessor::File;
|
||||
|
||||
|
@ -70,6 +70,7 @@ struct MemorySourceAccessor : virtual SourceAccessor
|
||||
File * open(const CanonPath & path, std::optional<File> create);
|
||||
|
||||
CanonPath addFile(CanonPath path, std::string && contents);
|
||||
CanonPath addSymlink(CanonPath path, std::string && contents);
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user