aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/depdb.cxx47
-rw-r--r--build2/depdb.hxx9
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 <libbutl/filesystem.mxx> // file_mtime()
+#include <build2/diagnostics.hxx>
+
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