From 47c4216da51e23c457e617df7b06577029908bb3 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Tue, 19 May 2020 22:10:48 -0400 Subject: [PATCH] removed logging of guessed process path, not very useful but very slow removed exists() check that was actually slower cow for env --- src/env.cpp | 172 ++++++++++++++++++++++++++++++++++++---------- src/env.h | 29 ++++++-- src/op.cpp | 5 +- src/process.cpp | 14 +--- src/tools/git.cpp | 10 +-- vs/mob.vcxproj | 1 + vs/release.props | 3 + 7 files changed, 170 insertions(+), 64 deletions(-) diff --git a/src/env.cpp b/src/env.cpp index 1a17709..c97e704 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -103,6 +103,36 @@ env env::vs(arch a) } } + +env::env() + : own_(false) +{ +} + +env::env(const env& e) + : data_(e.data_), own_(false) +{ +} + +env::env(env&& e) + : data_(std::move(e.data_)), own_(e.own_) +{ +} + +env& env::operator=(const env& e) +{ + data_ = e.data_; + own_ = false; + return *this; +} + +env& env::operator=(env&& e) +{ + data_ = std::move(e.data_); + own_ = e.own_; + return *this; +} + env& env::append_path(const fs::path& p) { return append_path(std::vector{p}); @@ -110,101 +140,169 @@ env& env::append_path(const fs::path& p) env& env::append_path(const std::vector& v) { - std::string path; + copy_for_write(); - auto itor = find("PATH"); - if (itor != vars_.end()) - path = itor->second; + std::wstring path; + + { + auto current = find(L"PATH"); + if (current) + path = *current; + } for (auto&& p : v) { if (!path.empty()) - path += ";"; + path += L";"; - path += path_to_utf8(p); + path += p.native(); } - set("PATH", path, replace); + set(L"PATH", path, replace); return *this; } -env& env::set(std::string k, std::string v, flags f) +env& env::set(std::string_view k, std::string_view v, flags f) { - auto itor = find(k); + copy_for_write(); + set_impl(utf8_to_utf16(k), utf8_to_utf16(v), f); + return *this; +} - if (itor == vars_.end()) +env& env::set(std::wstring k, std::wstring v, flags f) +{ + copy_for_write(); + set_impl(std::move(k), std::move(v), f); + return *this; +} + +void env::set_impl(std::wstring k, std::wstring v, flags f) +{ + auto current = find(k); + + if (!current) { - vars_[k] = v; - return *this; + data_->vars.emplace(std::move(k), std::move(v)); + return; } switch (f) { case replace: - vars_[itor->first] = v; + *current = std::move(v); break; case append: - vars_[itor->first] += v; + *current += v; break; case prepend: - vars_[itor->first] = v + vars_[itor->first]; + *current = v + *current; break; } - - return *this; } -std::string env::get(const std::string& k) const +std::string env::get(std::string_view k) const { - auto itor = find(k); - if (itor == vars_.end()) + if (!data_) return {}; - return itor->second; + auto current = find(utf8_to_utf16(k)); + if (!current) + return {}; + + return utf16_to_utf8(*current); } void env::set_from(const env& e) { - for (auto&& v : e.vars_) - set(v.first, v.second, replace); + copy_for_write(); + + if (e.data_) + { + for (auto&& v : e.data_->vars) + set_impl(v.first, v.second, replace); + } } void env::create() const { - sys_.clear(); + data_->sys.clear(); - for (auto&& v : vars_) + for (auto&& v : data_->vars) { - sys_ += utf8_to_utf16(v.first + "=" + v.second); - sys_.append(1, L'\0'); + data_->sys += v.first + L"=" + v.second; + data_->sys.append(1, L'\0'); } - sys_.append(1, L'\0'); + data_->sys.append(1, L'\0'); } -env::map::const_iterator env::find(const std::string& name) const +std::wstring* env::find(std::wstring_view name) { - for (auto itor=vars_.begin(); itor!=vars_.end(); ++itor) + if (!data_) + return {}; + + for (auto itor=data_->vars.begin(); itor!=data_->vars.end(); ++itor) { - if (_stricmp(itor->first.c_str(), name.c_str()) == 0) - return itor; + if (_wcsnicmp(itor->first.c_str(), name.data(), name.size()) == 0) + return &itor->second; } - return vars_.end(); + return {}; +} + +const std::wstring* env::find(std::wstring_view name) const +{ + if (!data_) + return {}; + + for (auto itor=data_->vars.begin(); itor!=data_->vars.end(); ++itor) + { + if (_wcsnicmp(itor->first.c_str(), name.data(), name.size()) == 0) + return &itor->second; + } + + return {}; } void* env::get_unicode_pointers() const { - if (vars_.empty()) + if (!data_ || data_->vars.empty()) return nullptr; - if (sys_.empty()) - create(); + { + std::scoped_lock lock(data_->m); + if (data_->sys.empty()) + create(); + } - return (void*)sys_.c_str(); + return (void*)data_->sys.c_str(); +} + +void env::copy_for_write() +{ + if (own_) + return; + + if (data_) + { + auto shared = data_; + data_.reset(new data); + data_->vars = shared->vars; + + { + std::scoped_lock lock(shared->m); + data_->sys = shared->sys; + } + } + else + { + data_.reset(new data); + } + + own_ = true; } diff --git a/src/env.h b/src/env.h index ed6abe3..1742153 100644 --- a/src/env.h +++ b/src/env.h @@ -19,24 +19,41 @@ public: static env vs_x64(); static env vs(arch a); + env(); + env(const env& e); + env(env&& e); + env& operator=(const env& e); + env& operator=(env&& e); + env& append_path(const fs::path& p); env& append_path(const std::vector& v); - env& set(std::string k, std::string v, flags f=replace); + env& set(std::string_view k, std::string_view v, flags f=replace); + env& set(std::wstring k, std::wstring v, flags f=replace); void set_from(const env& e); - std::string get(const std::string& k) const; + std::string get(std::string_view k) const; void* get_unicode_pointers() const; private: - using map = std::map; + using map = std::map; - map vars_; - mutable std::wstring sys_; + struct data + { + std::mutex m; + map vars; + mutable std::wstring sys; + }; + + std::shared_ptr data_; + bool own_; void create() const; - map::const_iterator find(const std::string& name) const; + std::wstring* find(std::wstring_view name); + const std::wstring* find(std::wstring_view name) const; + void set_impl(std::wstring k, std::wstring v, flags f); + void copy_for_write(); }; diff --git a/src/op.cpp b/src/op.cpp index f61a875..c8dfd3f 100644 --- a/src/op.cpp +++ b/src/op.cpp @@ -35,10 +35,7 @@ void create_directories(const context& cx, const fs::path& p) check(cx, p); if (!conf::dry()) - { - if (!fs::exists(p)) - do_create_directories(cx, p); - } + do_create_directories(cx, p); } void delete_directory(const context& cx, const fs::path& p, flags f) diff --git a/src/process.cpp b/src/process.cpp index afd9968..ba0ecc2 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -524,19 +524,7 @@ void process::do_run(const std::string& what) cwd_p = (cwd_s.empty() ? nullptr : cwd_s.c_str()); } - if (!bin_.empty()) - { - if (bin_.is_absolute()) - { - cx_->trace(context::cmd, "creating process {}", bin_); - } - else - { - cx_->trace(context::cmd, - "creating process, looks like it should spawn '{}'", - find_in_path(path_to_utf8(bin_.filename()))); - } - } + cx_->trace(context::cmd, "creating process"); const auto r = ::CreateProcessW( cmd.c_str(), args.data(), diff --git a/src/tools/git.cpp b/src/tools/git.cpp index 07644d8..d695ca0 100644 --- a/src/tools/git.cpp +++ b/src/tools/git.cpp @@ -176,11 +176,13 @@ void git::do_run() process git::make_process() { - return process() + static env e = this_env::get() + .set("GCM_INTERACTIVE", "never") + .set("GIT_TERMINAL_PROMPT", "0"); + + return std::move(process() .binary(binary()) - .env(this_env::get() - .set("GCM_INTERACTIVE", "never") - .set("GIT_TERMINAL_PROMPT", "0")); + .env(e)); } void git::do_add_submodule() diff --git a/vs/mob.vcxproj b/vs/mob.vcxproj index 68416b2..1f64e16 100644 --- a/vs/mob.vcxproj +++ b/vs/mob.vcxproj @@ -29,6 +29,7 @@ false v142 Unicode + true diff --git a/vs/release.props b/vs/release.props index 831aecb..451936a 100644 --- a/vs/release.props +++ b/vs/release.props @@ -16,6 +16,9 @@ true NDEBUG;%(PreprocessorDefinitions) + true + true + true