From 8456beeb0529b8dde7f4eea9a949c1c4f91a6120 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 21 Nov 2017 11:39:48 +0200 Subject: Diagnose failure to open depdb The cause is often a missing fsdir{} if the user tries to stash the target in a subdirectory. --- build2/depdb.cxx | 47 ++++++++++++++++++++++++++++++++--------------- build2/depdb.hxx | 9 ++++++++- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/build2/depdb.cxx b/build2/depdb.cxx index ee96efa..c041a0a 100644 --- a/build2/depdb.cxx +++ b/build2/depdb.cxx @@ -6,6 +6,8 @@ #include // file_mtime() +#include + using namespace std; using namespace butl; @@ -15,31 +17,46 @@ namespace build2 depdb (const path& f) : mtime_ (file_mtime (f)), touch_ (false) { - fs_.exceptions (fstream::failbit | fstream::badbit); + fstream::openmode om (fstream::out | fstream::binary); + fstream::iostate em (fstream::badbit); - if (mtime_ != timestamp_nonexistent) + if (mtime_ == timestamp_nonexistent) + { + mtime_ = timestamp_unknown; + state_ = state::write; + em |= fstream::failbit; + } + else { - // Open an existing file. - // - fs_.open (f.string (), fstream::in | fstream::out | fstream::binary); state_ = state::read; - fs_.exceptions (fstream::badbit); + om |= fstream::in; + } - // Read the database format version. - // + fs_.open (f.string (), om); + if (!fs_.is_open ()) + { + bool c (state_ == state::write); + + diag_record dr (fail); + dr << "unable to " << (c ? "create" : "open") << ' ' << f; + + if (c) + dr << info << "did you forget to add fsdir{} prerequisite for " + << "output directory?"; + } + + fs_.exceptions (em); + + // Read/write the database format version. + // + if (state_ == state::read) + { string* l (read ()); if (l == nullptr || *l != "1") write ('1'); } else - { - fs_.open (f.string (), fstream::out | fstream::binary); - - state_ = state::write; - mtime_ = timestamp_unknown; - write ('1'); - } } void depdb:: diff --git a/build2/depdb.hxx b/build2/depdb.hxx index 520642e..6c68d19 100644 --- a/build2/depdb.hxx +++ b/build2/depdb.hxx @@ -14,7 +14,8 @@ namespace build2 { // Auxiliary dependency database (those .d files). Uses io_error and - // system_error exceptions to signal errors. + // system_error exceptions to signal errors except for openning (see + // below). // // This is a strange beast: a line-oriented, streaming database that can, at // some point, be switched from reading to (over)writing. The idea is to @@ -64,6 +65,12 @@ namespace build2 // has wrong format version, or is corrupt, then the database will be // immediately switched to writing. // + // If the database cannot be opened, issue diagnostics and throw failed. + // This commonly happens when the user tries to stash the target in a + // non-existent subdirectory but forgets to add the corresponding fsdir{} + // prerequisite. Handling this as io_error in every rule that uses depdb + // would be burdensome thus we issue the diagnostics here. + // depdb (const path&); // Return the modification time of the database. This value only makes -- cgit v1.1