mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
PR-URL: https://github.com/nodejs/node/pull/49542 Refs: https://github.com/nodejs/node/issues/49148 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
170 lines
4.2 KiB
C++
170 lines
4.2 KiB
C++
#include "node_dotenv.h"
|
|
#include "env-inl.h"
|
|
#include "node_file.h"
|
|
#include "uv.h"
|
|
|
|
namespace node {
|
|
|
|
using v8::NewStringType;
|
|
using v8::String;
|
|
|
|
std::vector<std::string> Dotenv::GetPathFromArgs(
|
|
const std::vector<std::string>& args) {
|
|
const auto find_match = [](const std::string& arg) {
|
|
const std::string_view flag = "--env-file";
|
|
return strncmp(arg.c_str(), flag.data(), flag.size()) == 0;
|
|
};
|
|
std::vector<std::string> paths;
|
|
auto path = std::find_if(args.begin(), args.end(), find_match);
|
|
|
|
while (path != args.end()) {
|
|
auto equal_char = path->find('=');
|
|
|
|
if (equal_char != std::string::npos) {
|
|
paths.push_back(path->substr(equal_char + 1));
|
|
} else {
|
|
auto next_path = std::next(path);
|
|
|
|
if (next_path == args.end()) {
|
|
return paths;
|
|
}
|
|
|
|
paths.push_back(*next_path);
|
|
}
|
|
|
|
path = std::find_if(++path, args.end(), find_match);
|
|
}
|
|
|
|
return paths;
|
|
}
|
|
|
|
void Dotenv::SetEnvironment(node::Environment* env) {
|
|
if (store_.empty()) {
|
|
return;
|
|
}
|
|
|
|
auto isolate = env->isolate();
|
|
|
|
for (const auto& entry : store_) {
|
|
auto key = entry.first;
|
|
auto value = entry.second;
|
|
|
|
auto existing = env->env_vars()->Get(key.data());
|
|
|
|
if (existing.IsNothing()) {
|
|
env->env_vars()->Set(
|
|
isolate,
|
|
v8::String::NewFromUtf8(
|
|
isolate, key.data(), NewStringType::kNormal, key.size())
|
|
.ToLocalChecked(),
|
|
v8::String::NewFromUtf8(
|
|
isolate, value.data(), NewStringType::kNormal, value.size())
|
|
.ToLocalChecked());
|
|
}
|
|
}
|
|
}
|
|
|
|
void Dotenv::ParsePath(const std::string_view path) {
|
|
uv_fs_t req;
|
|
auto defer_req_cleanup = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });
|
|
|
|
uv_file file = uv_fs_open(nullptr, &req, path.data(), 0, 438, nullptr);
|
|
if (req.result < 0) {
|
|
// req will be cleaned up by scope leave.
|
|
return;
|
|
}
|
|
uv_fs_req_cleanup(&req);
|
|
|
|
auto defer_close = OnScopeLeave([file]() {
|
|
uv_fs_t close_req;
|
|
CHECK_EQ(0, uv_fs_close(nullptr, &close_req, file, nullptr));
|
|
uv_fs_req_cleanup(&close_req);
|
|
});
|
|
|
|
std::string result{};
|
|
char buffer[8192];
|
|
uv_buf_t buf = uv_buf_init(buffer, sizeof(buffer));
|
|
|
|
while (true) {
|
|
auto r = uv_fs_read(nullptr, &req, file, &buf, 1, -1, nullptr);
|
|
if (req.result < 0) {
|
|
// req will be cleaned up by scope leave.
|
|
return;
|
|
}
|
|
uv_fs_req_cleanup(&req);
|
|
if (r <= 0) {
|
|
break;
|
|
}
|
|
result.append(buf.base, r);
|
|
}
|
|
|
|
using std::string_view_literals::operator""sv;
|
|
auto lines = SplitString(result, "\n"sv);
|
|
|
|
for (const auto& line : lines) {
|
|
ParseLine(line);
|
|
}
|
|
}
|
|
|
|
void Dotenv::AssignNodeOptionsIfAvailable(std::string* node_options) {
|
|
auto match = store_.find("NODE_OPTIONS");
|
|
|
|
if (match != store_.end()) {
|
|
*node_options = match->second;
|
|
}
|
|
}
|
|
|
|
void Dotenv::ParseLine(const std::string_view line) {
|
|
auto equal_index = line.find('=');
|
|
|
|
if (equal_index == std::string_view::npos) {
|
|
return;
|
|
}
|
|
|
|
auto key = line.substr(0, equal_index);
|
|
|
|
// Remove leading and trailing space characters from key.
|
|
while (!key.empty() && std::isspace(key.front())) key.remove_prefix(1);
|
|
while (!key.empty() && std::isspace(key.back())) key.remove_suffix(1);
|
|
|
|
// Omit lines with comments
|
|
if (key.front() == '#' || key.empty()) {
|
|
return;
|
|
}
|
|
|
|
auto value = std::string(line.substr(equal_index + 1));
|
|
|
|
// Might start and end with `"' characters.
|
|
auto quotation_index = value.find_first_of("`\"'");
|
|
|
|
if (quotation_index == 0) {
|
|
auto quote_character = value[quotation_index];
|
|
value.erase(0, 1);
|
|
|
|
auto end_quotation_index = value.find_last_of(quote_character);
|
|
|
|
// We couldn't find the closing quotation character. Terminate.
|
|
if (end_quotation_index == std::string::npos) {
|
|
return;
|
|
}
|
|
|
|
value.erase(end_quotation_index);
|
|
} else {
|
|
auto hash_index = value.find('#');
|
|
|
|
// Remove any inline comments
|
|
if (hash_index != std::string::npos) {
|
|
value.erase(hash_index);
|
|
}
|
|
|
|
// Remove any leading/trailing spaces from unquoted values.
|
|
while (!value.empty() && std::isspace(value.front())) value.erase(0, 1);
|
|
while (!value.empty() && std::isspace(value.back()))
|
|
value.erase(value.size() - 1);
|
|
}
|
|
|
|
store_.insert_or_assign(std::string(key), value);
|
|
}
|
|
|
|
} // namespace node
|