fixed a few leaking exceptions

force filenames for stylesheets, some are just version numbers
changed curl downloader to use CreateFile(), was getting access denied errors
fixed curl sometimes getting stuck
sip has to start downloading after python because it uses python.exe
fixed op::check() to be case insensitive
better message when important variables are missing
bootstrap: uses vcvars, multi process
This commit is contained in:
isanae
2020-05-06 07:43:15 -04:00
parent f30fe785d5
commit 932495f36d
15 changed files with 267 additions and 64 deletions
+33 -1
View File
@@ -1 +1,33 @@
@msbuild vs/builder.sln -m -p:Configuration=Release -noLogo -clp:ErrorsOnly;Verbosity=minimal
@echo off
Setlocal EnableDelayedExpansion
set "vswhere_cmd=third-party\bin\vswhere.exe -nologo -prerelease -latest -property installationPath"
for /F "tokens=* USEBACKQ" %%F in (`%vswhere_cmd%`) do (
set ret=%errorlevel%
if %errorlevel% neq 0 (
echo %%F
echo vswhere returned %ret%
exit /b 1
)
set installation_path=%%F
if "%installation_path%" == "" (
echo empty installation path
exit /b 1
)
)
set "opts="
set "opts=%opts% vs/mob.sln"
set "opts=%opts% -m "
set "opts=%opts% -p:Configuration=Release"
set "opts=%opts% -noLogo "
set "opts=%opts% -p:UseMultiToolTask=true"
set "opts=%opts% -p:EnforceProcessCountAcrossBuilds=true"
set "opts=%opts% -clp:ErrorsOnly;Verbosity=minimal"
set "vcvars=%installation_path%\VC\Auxiliary\Build\vcvarsall.bat"
cmd /c ""%vcvars%" amd64 > NUL && msbuild %opts%"
echo run `mob` to start building
+22 -11
View File
@@ -277,13 +277,15 @@ void dump_available_options()
bool try_parts(fs::path& check, const std::vector<std::string>& parts)
{
for (std::size_t i=0; i<parts.size() - 1; ++i)
for (std::size_t i=0; i<parts.size(); ++i)
{
fs::path p = check;
for (std::size_t j=i; j<parts.size(); ++j)
p /= parts[j];
gcx().trace(context::conf, "trying parts " + p.string());
if (fs::exists(p))
{
check = p;
@@ -702,29 +704,38 @@ void check_missing_options()
{
if (conf::mo_org().empty())
{
gcx().bail_out(context::conf,
"missing mo_org; either specify it the [options] section of "
"the ini or pass '-s options/mo_org=something'");
std::cerr
<< "missing mo_org; either specify it the [options] section of "
<< "the ini or pass '-s options/mo_org=something'\n";
throw bailed("");
}
if (conf::mo_branch().empty())
{
gcx().bail_out(context::conf,
"missing mo_branch; either specify it the [options] section of "
"the ini or pass '-s options/mo_org=something'");
std::cerr
<< "missing mo_branch; either specify it the [options] section of "
<< "the ini or pass '-s options/mo_org=something'\n";
throw bailed("");
}
if (paths::prefix().empty())
{
gcx().bail_out(context::conf,
"missing prefix; either specify it the [paths] section of "
"the ini or pass '-d path'");
std::cerr
<< "missing prefix; either specify it the [paths] section of "
<< "the ini or pass '-d path'\n";
throw bailed("");
}
for (auto&& [k, v] : g_versions)
{
if (v.empty())
gcx().bail_out(context::conf, "missing version for " + k);
{
std::cerr << "missing version for " << k << "\n";
throw bailed("");
}
}
}
+19 -2
View File
@@ -181,6 +181,16 @@ int run(int argc, char** argv)
{
if (auto r=handle_command_line(argc, argv))
return *r;
}
catch(bailed&)
{
// silent
return 1;
}
try
{
::SetConsoleCtrlHandler(signal_handler, TRUE);
@@ -208,8 +218,15 @@ int main(int argc, char** argv)
{
int r = mob::run(argc, argv);
mob::gcx().debug(mob::context::generic,
"mob finished with exit code " + std::to_string(r));
if (r == 0)
{
mob::gcx().debug(mob::context::generic, "mob done");
}
else
{
mob::gcx().debug(mob::context::generic,
"mob finished with exit code " + std::to_string(r));
}
mob::dump_logs();
+80 -6
View File
@@ -72,7 +72,17 @@ void curl_downloader::start(const url& u, const fs::path& path)
if (conf::dry())
return;
thread_ = std::thread([&] { run(); });
thread_ = std::thread([&]
{
try
{
run();
}
catch(...)
{
// eat it
}
});
}
void curl_downloader::join()
@@ -104,6 +114,11 @@ void curl_downloader::run()
curl_easy_setopt(c, CURLOPT_URL, url_.c_str());
curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, on_write_static);
curl_easy_setopt(c, CURLOPT_WRITEDATA, this);
curl_easy_setopt(c, CURLOPT_PROGRESSFUNCTION, on_progress_static);
curl_easy_setopt(c, CURLOPT_PROGRESSDATA, this);
curl_easy_setopt(c, CURLOPT_XFERINFOFUNCTION, on_xfer_static);
curl_easy_setopt(c, CURLOPT_XFERINFODATA, this);
curl_easy_setopt(c, CURLOPT_NOPROGRESS, 0l);
curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1l);
curl_easy_setopt(c, CURLOPT_ERRORBUFFER, error_buffer);
@@ -120,7 +135,11 @@ void curl_downloader::run()
const auto r = curl_easy_perform(c);
cx_.trace(context::net, "curl: transfer finished " + url_.string());
file_.reset();
if (file_)
{
::FlushFileBuffers(file_.get());
file_.reset();
}
if (interrupt_)
{
@@ -152,8 +171,8 @@ void curl_downloader::run()
{
cx_.error(context::net,
std::string("curl: ") +
curl_easy_strerror(r) + ", " + error_buffer + ", " +
url_.string());
curl_easy_strerror(r) + ", " + trim_copy(error_buffer) + " " +
"(" + url_.string() + ")");
}
}
@@ -169,6 +188,13 @@ size_t curl_downloader::on_write_static(
}
self->on_write(ptr, size * nmemb);
if (self->interrupt_)
{
debug("downloader: interrupting");
return (size * nmemb) + 1; // force failure
}
return size * nmemb;
}
@@ -179,11 +205,59 @@ void curl_downloader::on_write(char* ptr, std::size_t n) noexcept
op::create_directories(cx_, path_.parent_path());
cx_.trace(context::net, "opening " + path_.string());
file_.reset(_wfopen(path_.native().c_str(), L"wb"));
HANDLE h = ::CreateFileA(
path_.string().c_str(), GENERIC_WRITE, FILE_SHARE_READ,
nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (h == INVALID_HANDLE_VALUE)
{
const auto e = GetLastError();
cx_.error(context::net, "failed to open " + path_.string(), e);
interrupt_ = true;
return;
}
file_.reset(h);
}
bytes_ += n;
std::fwrite(ptr, n, 1, file_.get());
DWORD written = 0;
if (!::WriteFile(file_.get(), ptr, static_cast<DWORD>(n), &written, nullptr))
{
const auto e = GetLastError();
cx_.error(context::net, "failed to write to " + path_.string(), e);
interrupt_ = true;
}
}
int curl_downloader::on_progress_static(
void* user, double, double, double, double) noexcept
{
auto* self = static_cast<curl_downloader*>(user);
if (self->interrupt_)
{
debug("downloader: interrupting");
return 1;
}
return 0;
}
int curl_downloader::on_xfer_static(
void* user, curl_off_t, curl_off_t, curl_off_t, curl_off_t) noexcept
{
auto* self = static_cast<curl_downloader*>(user);
if (self->interrupt_)
{
debug("downloader: interrupting");
return 1;
}
return 0;
}
int curl_downloader::on_debug_static(
+8 -1
View File
@@ -48,7 +48,7 @@ private:
const context& cx_;
url url_;
fs::path path_;
file_ptr file_;
handle_ptr file_;
std::thread thread_;
std::size_t bytes_;
std::atomic<bool> interrupt_;
@@ -61,6 +61,13 @@ private:
void on_write(char* ptr, std::size_t n) noexcept;
static int on_progress_static(
void* user, double dltotal, double dlnow,
double ultotal, double ulnow) noexcept;
static int on_xfer_static(
void* user, curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow) noexcept;
static int on_debug_static(
CURL* handle, curl_infotype type,
+19 -3
View File
@@ -484,13 +484,29 @@ void check(const context& cx, const fs::path& p)
if (p.empty())
cx.bail_out(context::fs, "path is empty");
if (p.native().starts_with(paths::prefix().native()))
auto is_inside = [](auto&& p, auto&& dir)
{
const std::string s = p.string();
const std::string prefix = dir.string();
if (s.size() < prefix.size())
return false;
const std::string scut = s.substr(0, prefix.size());
if (_stricmp(scut.c_str(), prefix.c_str()) != 0)
return false;
return true;
};
if (is_inside(p, paths::prefix()))
return;
if (p.native().starts_with(paths::temp_dir().native()))
if (is_inside(p, paths::temp_dir()))
return;
if (p.native().starts_with(paths::licenses().native()))
if (is_inside(p, paths::licenses()))
return;
cx.bail_out(context::fs, "path " + p.string() + " is outside prefix");
+3
View File
@@ -607,7 +607,10 @@ void process::on_completed()
// success
if (code_ == 0)
{
cx_->trace(context::cmd, "process exit code is 0");
return;
}
if (flags_ & allow_failure)
{
+11 -9
View File
@@ -46,12 +46,23 @@ void sip::do_clean_for_rebuild()
}
void sip::do_fetch()
{
// downloading uses python.exe and so has to wait until it's built
}
void sip::do_build_and_install()
{
download();
run_tool(extractor()
.file(download_file())
.output(source_path()));
generate();
op::copy_file_to_dir_if_better(cx(),
source_path() / "sip.h",
python::include_path());
}
void sip::download()
@@ -84,15 +95,6 @@ void sip::download()
.arg("sip==" + versions::sip())));
}
void sip::do_build_and_install()
{
generate();
op::copy_file_to_dir_if_better(cx(),
source_path() / "sip.h",
python::include_path());
}
void sip::generate()
{
const auto header = source_path() / "sip.h";
+5 -3
View File
@@ -22,9 +22,11 @@ void stylesheets::do_fetch()
for (auto&& r : releases())
{
const auto file = run_tool(downloader(
"https://github.com/" + r.repo + "/" + r.name + "/releases/"
"download/v" + r.version + "/" + r.file + ".7z"));
const auto file = run_tool(downloader()
.url(
"https://github.com/" + r.repo + "/" + r.name + "/releases/"
"download/v" + r.version + "/" + r.file + ".7z")
.file(paths::cache() / (r.name + ".7z")));
run_tool(extractor()
.file(file)
+2 -1
View File
@@ -232,7 +232,8 @@ void task::fetch()
if (!get_source_path().empty())
{
cx().info(context::generic, "patching");
cx().debug(context::generic, "patching");
run_tool(patcher()
.task(name())
.root(get_source_path()));
+43 -21
View File
@@ -17,9 +17,13 @@ downloader::downloader(mob::url u)
downloader& downloader::url(const mob::url& u)
{
cx_->trace(context::net, "adding url " + u.string());
urls_.push_back(u);
return *this;
}
downloader& downloader::file(const fs::path& p)
{
file_ = p;
return *this;
}
@@ -34,28 +38,23 @@ void downloader::do_run()
cx_->trace(context::net, "looking for already downloaded files");
for (auto&& u : urls_)
if (!file_.empty())
{
const auto file = path_for_url(u);
if (fs::exists(file))
if (try_picking(file_))
return;
}
else
{
for (auto&& u : urls_)
{
if (conf::redownload())
const auto file = path_for_url(u);
if (try_picking(file))
{
cx_->trace(context::redownload, "deleting " + file.string());
op::delete_file(*cx_, file, op::optional);
}
else
{
cx_->trace(context::bypass, "picking " + file_.string());
file_ = file;
return;
}
}
else
{
cx_->trace(context::net, "no " + file.string());
}
}
@@ -67,19 +66,19 @@ void downloader::do_run()
// try them in order
for (auto&& u : urls_)
{
const fs::path file = path_for_url(u);
if (file_.empty())
file_ = path_for_url(u);
cx_->trace(context::net,
"trying " + u.string() + " into " + file.string());
"trying " + u.string() + " into " + file_.string());
dl_->start(u, file);
dl_->start(u, file_);
cx_->trace(context::net, "waiting for download");
dl_->join();
if (dl_->ok())
{
cx_->trace(context::net, "file " + file.string() + " downloaded");
file_ = file;
cx_->trace(context::net, "file " + file_.string() + " downloaded");
return;
}
@@ -102,6 +101,29 @@ void downloader::do_interrupt()
dl_->interrupt();
}
bool downloader::try_picking(const fs::path& file)
{
if (fs::exists(file))
{
if (conf::redownload())
{
cx_->trace(context::redownload, "deleting " + file.string());
op::delete_file(*cx_, file, op::optional);
}
else
{
cx_->trace(context::bypass, "picking " + file_.string());
return true;
}
}
else
{
cx_->trace(context::net, "no " + file.string());
}
return false;
}
fs::path downloader::path_for_url(const mob::url& u) const
{
std::string filename;
+1 -1
View File
@@ -48,7 +48,7 @@ void tool::interrupt()
{
if (!interrupted_)
{
cx_->info(context::interruption, "interrupting " + name_);
cx_->debug(context::interruption, "interrupting " + name_);
interrupted_ = true;
do_interrupt();
}
+2
View File
@@ -49,6 +49,7 @@ public:
downloader(mob::url u);
downloader& url(const mob::url& u);
downloader& file(const fs::path& p);
fs::path result() const;
@@ -62,6 +63,7 @@ private:
std::vector<mob::url> urls_;
fs::path path_for_url(const mob::url& u) const;
bool try_picking(const fs::path& file);
};
+18 -4
View File
@@ -84,8 +84,15 @@ file_deleter::file_deleter(const context& cx, fs::path p)
file_deleter::~file_deleter()
{
if (delete_)
delete_now();
try
{
if (delete_)
delete_now();
}
catch(...)
{
// eat it
}
}
void file_deleter::delete_now()
@@ -109,8 +116,15 @@ directory_deleter::directory_deleter(const context& cx, fs::path p)
directory_deleter::~directory_deleter()
{
if (delete_)
delete_now();
try
{
if (delete_)
delete_now();
}
catch(...)
{
// eat it
}
}
void directory_deleter::delete_now()
+1 -1
View File
@@ -73,7 +73,7 @@
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>