36 namespace fable::schema {
41 const char* path_state_cstr(PathState e);
45 template <
typename TPath>
46 bool exists(
const TPath& path);
48 template <
typename TPath>
49 bool is_regular_file(
const TPath& path);
51 template <
typename TPath>
52 bool is_directory(
const TPath& path);
54 template <
typename TPath>
55 bool is_other(
const TPath& path);
57 template <
typename TPath>
58 TPath canonical(
const TPath& path);
60 template <
typename TPath>
61 std::optional<TPath> search_path(
const TPath& executable);
70 if (!pattern_.empty()) {
71 j[
"pattern"] = pattern_;
73 if (min_length_ != 0) {
74 j[
"minLength"] = min_length_;
76 if (max_length_ != std::numeric_limits<size_t>::max()) {
77 j[
"maxLength"] = max_length_;
80 if (req_state_ != State::Any) {
81 j[
"comment"] = detail::path_state_cstr(req_state_);
84 this->augment_schema(j);
90 if (!this->validate_type(c, err)) {
94 auto src = c.
get<std::string>();
97 src = interpolate_vars(src, env_);
99 if (src.size() < min_length_) {
100 return this->set_error(err, c,
"expect minimum path length of {}, got {}", min_length_,
103 if (src.size() > max_length_) {
104 return this->set_error(err, c,
"expect maximum path length of {}, got {}", max_length_,
107 if (!pattern_.empty() && !std::regex_match(src, std::regex(pattern_))) {
108 return this->set_error(err, c,
"expect path to match regex '{}': {}", pattern_, src);
112 if (req_abs_ && !p.is_absolute()) {
113 return this->set_error(err, c,
"expect path to be absolute: {}", src);
117 p = resolve_path(c, p);
119 err.emplace(std::move(e));
124 switch (req_state_) {
126 if (detail::exists(p)) {
127 return this->set_error(err, c, detail::path_state_cstr(req_state_));
131 if (!detail::exists(p)) {
132 return this->set_error(err, c, detail::path_state_cstr(req_state_));
135 case State::Executable:
137 case State::FileExists:
138 if (!detail::is_regular_file(p)) {
139 return this->set_error(err, c, detail::path_state_cstr(req_state_));
142 case State::DirExists:
143 if (!detail::is_directory(p)) {
144 return this->set_error(err, c, detail::path_state_cstr(req_state_));
148 if (detail::is_regular_file(p) || detail::is_other(p)) {
149 return this->set_error(err, c, detail::path_state_cstr(req_state_));
153 if (detail::is_directory(p)) {
154 return this->set_error(err, c, detail::path_state_cstr(req_state_));
164 template <
typename T>
166 auto s = c.
get<std::string>();
168 s = interpolate_vars(s, env_);
172 p = resolve_path(c, p);
175 p = detail::canonical(p);
180 template <
typename T>
181 typename Path<T>::Type Path<T>::resolve_path(
const Conf& c,
const Path<T>::Type& filepath)
const {
182 std::string filepath_str = filepath.generic_string();
186 if (req_state_ == State::Executable && filepath_str.find(
'/') == std::string::npos) {
187 auto result = detail::search_path(filepath);
189 throw this->error(c,
"expect executable to exist: {}", filepath.native());
193 return c.resolve_file(filepath_str);
T get() const
Definition: conf.hpp:166
Definition: error.hpp:130
bool validate(const Conf &c, std::optional< SchemaError > &err) const override
Definition: path_impl.hpp:89
Json json_schema() const override
Definition: path_impl.hpp:66
nlohmann::json Json
Definition: fable_fwd.hpp:35