aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bpkg/archive.cxx7
-rw-r--r--bpkg/auth.cxx110
-rw-r--r--bpkg/cfg-create.cxx32
-rw-r--r--bpkg/checksum2
-rw-r--r--bpkg/checksum.cxx89
-rw-r--r--bpkg/fetch.cxx95
-rw-r--r--bpkg/help.cxx8
-rw-r--r--bpkg/pkg-verify.cxx26
-rw-r--r--bpkg/rep-create.cxx17
-rw-r--r--bpkg/rep-fetch.cxx2
10 files changed, 196 insertions, 192 deletions
diff --git a/bpkg/archive.cxx b/bpkg/archive.cxx
index 0edf09d..f0596bf 100644
--- a/bpkg/archive.cxx
+++ b/bpkg/archive.cxx
@@ -93,15 +93,14 @@ namespace bpkg
try
{
- ifdstream is (pr.in_ofd);
-
// Do not throw when eofbit is set (end of stream reached), and
// when failbit is set (getline() failed to extract any character).
//
- is.exceptions (ifdstream::badbit);
+ ifdstream is (pr.in_ofd, ifdstream::badbit);
string s;
getline (is, s, '\0');
+ is.close ();
if (pr.wait ())
return s;
@@ -113,7 +112,7 @@ namespace bpkg
// Child exit status doesn't matter. Just wait for the process
// completion and fall through.
//
- pr.wait ();
+ pr.wait (); // Check throw.
}
// While it is reasonable to assuming the child process issued diagnostics
diff --git a/bpkg/auth.cxx b/bpkg/auth.cxx
index c152834..a9eaa76 100644
--- a/bpkg/auth.cxx
+++ b/bpkg/auth.cxx
@@ -4,9 +4,9 @@
#include <bpkg/auth>
+#include <ios>
#include <ratio>
#include <limits> // numeric_limits
-#include <fstream>
#include <cstring> // strlen(), strcmp()
#include <iterator> // ostreambuf_iterator, istreambuf_iterator
@@ -118,21 +118,20 @@ namespace bpkg
process pr (start_openssl (
co, "x509", {"-sha256", "-noout", "-fingerprint"}, true, true));
- ifdstream is (pr.in_ofd);
- is.exceptions (ifdstream::badbit);
-
try
{
+ ifdstream is (pr.in_ofd, fdstream_mode::skip);
ofdstream os (pr.out_fd);
- os.exceptions (ofdstream::badbit);
os << pem;
os.close ();
string s;
+ getline (is, s);
+ is.close ();
+
const size_t n (19);
- if (!(getline (is, s) && s.size () > n &&
- s.compare (0, n, "SHA256 Fingerprint=") == 0))
- throw istream::failure ("");
+ if (!(s.size () > n && s.compare (0, n, "SHA256 Fingerprint=") == 0))
+ throw ifdstream::failure ("");
string fp;
@@ -142,27 +141,21 @@ namespace bpkg
}
catch (const invalid_argument&)
{
- throw istream::failure ("");
+ throw ifdstream::failure ("");
}
- is.close ();
-
if (pr.wait ())
return fp;
// Fall through.
//
}
- catch (const istream::failure&)
+ catch (const ios_base::failure&)
{
- // Child input writing or output reading error.
- //
- is.close ();
-
// Child exit status doesn't matter. Just wait for the process
// completion and fall through.
//
- pr.wait ();
+ pr.wait (); // Check throw.
}
error << "unable to calculate certificate fingerprint for "
@@ -267,13 +260,14 @@ namespace bpkg
true,
true));
- ifdstream is (pr.in_ofd);
- is.exceptions (ifdstream::badbit);
-
try
{
+ // We unset failbit to provide the detailed error description (which
+ // certificate field is missed) on failure.
+ //
+ ifdstream is (pr.in_ofd, fdstream_mode::skip, ifdstream::badbit);
+
ofdstream os (pr.out_fd);
- os.exceptions (ofdstream::badbit);
// Reading from and writing to the child process standard streams from
// the same thread is generally a bad idea. Depending on the program
@@ -413,27 +407,15 @@ namespace bpkg
// Fall through.
//
}
- catch (const istream::failure&)
+ catch (const ios_base::failure&)
{
- // Child input writing or output reading error.
- //
- is.close ();
-
// Child exit status doesn't matter. Just wait for the process
// completion and fall through.
//
- pr.wait ();
+ pr.wait (); // Check throw.
}
catch (const invalid_argument& e)
{
- // Certificate parsing error. Skip until the end, not to offend the
- // child with the broken pipe. Never knows how it will take it.
- //
- if (!is.eof ())
- is.ignore (numeric_limits<streamsize>::max ());
-
- is.close ();
-
// If the child exited with an error status, then omit any output
// parsing diagnostics since we were probably parsing garbage.
//
@@ -570,14 +552,13 @@ namespace bpkg
try
{
- ofstream ofs;
- ofs.exceptions (ofstream::badbit | ofstream::failbit);
- ofs.open (f.string ());
+ ofdstream ofs (f);
ofs << *pem;
+ ofs.close ();
}
- catch (const ofstream::failure&)
+ catch (const ofdstream::failure& e)
{
- fail << "unable to write certificate to " << f;
+ fail << "unable to write certificate to " << f << ": " << e.what ();
}
}
@@ -656,15 +637,15 @@ namespace bpkg
{
f = path::temp_path ("bpkg");
- ofstream ofs;
- ofs.exceptions (ofstream::badbit | ofstream::failbit);
- ofs.open (f.string ());
+ ofdstream ofs (f);
rm = auto_rmfile (f);
ofs << *cert_pem;
+ ofs.close ();
}
- catch (const ofstream::failure&)
+ catch (const ofdstream::failure& e)
{
- fail << "unable to save certificate to temporary file " << f;
+ fail << "unable to save certificate to temporary file " << f
+ << ": " << e.what ();
}
catch (const system_error& e)
{
@@ -702,15 +683,13 @@ namespace bpkg
true,
true));
- ifdstream is (pr.in_ofd);
- is.exceptions (ifdstream::badbit);
-
try
{
+ ifdstream is (pr.in_ofd, fdstream_mode::skip);
+
// Write the signature to the openssl process input in the binary mode.
//
- ofdstream os (pr.out_fd, fdtranslate::binary);
- os.exceptions (ofdstream::badbit);
+ ofdstream os (pr.out_fd, fdstream_mode::binary);
for (const auto& c: sm.signature)
os.put (c); // Sets badbit on failure.
@@ -718,7 +697,9 @@ namespace bpkg
os.close ();
string s;
- bool v (getline (is, s) && is.eof ());
+ getline (is, s);
+
+ bool v (is.eof ());
is.close ();
if (pr.wait () && v)
@@ -733,16 +714,12 @@ namespace bpkg
// Fall through.
//
}
- catch (const istream::failure&)
+ catch (const ios_base::failure&)
{
- // Child input writing or output reading error.
- //
- is.close ();
-
// Child exit status doesn't matter. Just wait for the process
// completion and fall through.
//
- pr.wait ();
+ pr.wait (); // Check throw.
}
error << "unable to authenticate repository " << rl.canonical_name ();
@@ -793,15 +770,14 @@ namespace bpkg
process pr (start_openssl (
co, "pkeyutl", {"-sign", "-inkey", key_name.c_str ()}, true, true));
- // Read the signature from the openssl process output in the binary mode.
- //
- ifdstream is (pr.in_ofd, fdtranslate::binary);
- is.exceptions (ifdstream::badbit);
-
try
{
+ // Read the signature from the openssl process output in the binary
+ // mode.
+ //
+ ifdstream is (pr.in_ofd, fdstream_mode::binary | fdstream_mode::skip);
+
ofdstream os (pr.out_fd);
- os.exceptions (ofdstream::badbit);
os << sha256sum;
os.close ();
@@ -819,16 +795,12 @@ namespace bpkg
// Fall through.
//
}
- catch (const istream::failure&)
+ catch (const iostream::failure&)
{
- // Child input writing or output reading error.
- //
- is.close ();
-
// Child exit status doesn't matter. Just wait for the process
// completion and fall through.
//
- pr.wait ();
+ pr.wait (); // Check throw.
}
error << "unable to sign repository " << r;
diff --git a/bpkg/cfg-create.cxx b/bpkg/cfg-create.cxx
index 3d2121e..b5b1f41 100644
--- a/bpkg/cfg-create.cxx
+++ b/bpkg/cfg-create.cxx
@@ -4,7 +4,7 @@
#include <bpkg/cfg-create>
-#include <fstream>
+#include <butl/fdstream>
#include <bpkg/package>
#include <bpkg/package-odb>
@@ -72,9 +72,7 @@ namespace bpkg
path f (b / path ("bootstrap.build"));
try
{
- ofstream ofs;
- ofs.exceptions (ofstream::badbit | ofstream::failbit);
- ofs.open (f.string ());
+ ofdstream ofs (f);
ofs << "# Maintained automatically by bpkg. Edit if you know what " <<
"you are doing." << endl
@@ -85,10 +83,12 @@ namespace bpkg
<< "using config" << endl
<< "using test" << endl
<< "using install" << endl;
+
+ ofs.close ();
}
- catch (const ofstream::failure&)
+ catch (const ofdstream::failure& e)
{
- fail << "unable to write to " << f;
+ fail << "unable to write to " << f << ": " << e.what ();
}
// Write build/root.build.
@@ -96,9 +96,7 @@ namespace bpkg
f = b / path ("root.build");
try
{
- ofstream ofs;
- ofs.exceptions (ofstream::badbit | ofstream::failbit);
- ofs.open (f.string ());
+ ofdstream ofs (f);
ofs << "# Maintained automatically by bpkg. Edit if you know what " <<
"you are doing." << endl
@@ -109,10 +107,12 @@ namespace bpkg
//
for (const string& m: mods)
ofs << "using " << m << endl;
+
+ ofs.close ();
}
- catch (const ofstream::failure&)
+ catch (const ofdstream::failure& e)
{
- fail << "unable to write to " << f;
+ fail << "unable to write to " << f << ": " << e.what ();
}
// Write root buildfile.
@@ -120,18 +120,18 @@ namespace bpkg
f = c / path ("buildfile");
try
{
- ofstream ofs;
- ofs.exceptions (ofstream::badbit | ofstream::failbit);
- ofs.open (f.string ());
+ ofdstream ofs (f);
ofs << "# Maintained automatically by bpkg. Edit if you know what " <<
"you are doing." << endl
<< "#" << endl
<< "./:" << endl;
+
+ ofs.close ();
}
- catch (const ofstream::failure&)
+ catch (const ofdstream::failure& e)
{
- fail << "unable to write to " << f;
+ fail << "unable to write to " << f << ": " << e.what ();
}
// Configure.
diff --git a/bpkg/checksum b/bpkg/checksum
index 3ef35cc..c0dbb6b 100644
--- a/bpkg/checksum
+++ b/bpkg/checksum
@@ -18,7 +18,7 @@ namespace bpkg
string
sha256 (const common_options&, const char* buf, size_t n);
- // The same but for a stream (if ifstream, open in binary mode).
+ // The same but for a stream (if ifdstream, open in binary mode).
//
string
sha256 (const common_options&, istream&);
diff --git a/bpkg/checksum.cxx b/bpkg/checksum.cxx
index 3c9c4e5..023e641 100644
--- a/bpkg/checksum.cxx
+++ b/bpkg/checksum.cxx
@@ -4,7 +4,6 @@
#include <bpkg/checksum>
-#include <fstream>
#include <streambuf>
#include <butl/process>
@@ -36,21 +35,33 @@ namespace bpkg
{
process pr (args, 0, -1, 1); // Redirect STDOUT and STDERR to a pipe.
- ifdstream is (pr.in_ofd);
- string l;
- getline (is, l);
+ try
+ {
+ ifdstream is (pr.in_ofd);
+
+ string l;
+ getline (is, l);
+ is.close ();
- return
- l == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
- && pr.wait ();
+ return
+ pr.wait () &&
+ l ==
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
+ }
+ catch (const ifdstream::failure&)
+ {
+ // Fall through.
+ }
}
catch (const process_error& e)
{
if (e.child ())
exit (1);
- return false;
+ // Fall through.
}
+
+ return false;
}
static process
@@ -89,19 +100,30 @@ namespace bpkg
{
process pr (args, 0, -1); // Redirect STDOUT to a pipe.
- ifdstream is (pr.in_ofd);
- string l;
- getline (is, l);
+ try
+ {
+ ifdstream is (pr.in_ofd, fdstream_mode::skip);
+
+ string l;
+ getline (is, l);
+ is.close ();
- return l.compare (0, 9, "sha256sum") == 0 && pr.wait ();
+ return pr.wait () && l.compare (0, 9, "sha256sum") == 0;
+ }
+ catch (const ifdstream::failure&)
+ {
+ // Fall through.
+ }
}
catch (const process_error& e)
{
if (e.child ())
exit (1);
- return false;
+ // Fall through.
}
+
+ return false;
}
static process
@@ -140,19 +162,30 @@ namespace bpkg
{
process pr (args, 0, -1); // Redirect STDOUT to a pipe.
- ifdstream is (pr.in_ofd);
- string l;
- getline (is, l);
+ try
+ {
+ ifdstream is (pr.in_ofd);
+
+ string l;
+ getline (is, l);
+ is.close ();
- return l.size () != 0 && l[0] >= '0' && l[0] <= '9' && pr.wait ();
+ return pr.wait () && l.size () != 0 && l[0] >= '0' && l[0] <= '9';
+ }
+ catch (const ifdstream::failure&)
+ {
+ // Fall through.
+ }
}
catch (const process_error& e)
{
if (e.child ())
exit (1);
- return false;
+ // Fall through.
}
+
+ return false;
}
static process
@@ -273,7 +306,7 @@ namespace bpkg
// Prevent any data modifications on the way to the hashing program.
//
- fdmode (pr.out_fd, fdtranslate::binary);
+ fdmode (pr.out_fd, fdstream_mode::binary);
return pr;
}
catch (const process_error& e)
@@ -294,11 +327,8 @@ namespace bpkg
try
{
+ ifdstream is (pr.in_ofd, fdstream_mode::skip);
ofdstream os (pr.out_fd);
- os.exceptions (ofdstream::badbit | ofdstream::failbit);
-
- ifdstream is (pr.in_ofd);
- is.exceptions (ifdstream::badbit | ifdstream::failbit);
os << &sb;
os.close ();
@@ -319,7 +349,7 @@ namespace bpkg
return s;
}
- // Child existed with an error, fall through.
+ // Child exited with an error, fall through.
}
// Ignore these exceptions if the child process exited with an error status
// since that's the source of the failure.
@@ -373,17 +403,12 @@ namespace bpkg
try
{
- ifstream ifs (f.string (), ios::binary);
- if (!ifs.is_open ())
- fail << "unable to open " << f << " in read mode";
-
- ifs.exceptions (ofstream::badbit | ofstream::failbit);
-
+ ifdstream ifs (f, ios::binary);
return sha256 (o, ifs);
}
- catch (const iostream::failure&)
+ catch (const iostream::failure& e)
{
- error << "unable read " << f;
+ error << "unable read " << f << ": " << e.what ();
throw failed ();
}
}
diff --git a/bpkg/fetch.cxx b/bpkg/fetch.cxx
index c4e441a..e095785 100644
--- a/bpkg/fetch.cxx
+++ b/bpkg/fetch.cxx
@@ -4,7 +4,6 @@
#include <bpkg/fetch>
-#include <fstream>
#include <sstream>
#include <butl/process>
@@ -44,12 +43,22 @@ namespace bpkg
{
process pr (args, 0, -1); // Redirect STDOUT to a pipe.
- ifdstream is (pr.in_ofd);
string l;
- getline (is, l);
- if (l.compare (0, 9, "GNU Wget ") != 0)
+ try
+ {
+ ifdstream is (pr.in_ofd, fdstream_mode::skip);
+
+ getline (is, l);
+ is.close ();
+
+ if (!(pr.wait () && l.compare (0, 9, "GNU Wget ") == 0))
+ return false;
+ }
+ catch (const ifdstream::failure&)
+ {
return false;
+ }
// Extract the version. If something goes wrong, set the version
// to 0 so that we treat it as a really old wget.
@@ -74,7 +83,7 @@ namespace bpkg
l4 ([&]{trace << "unable to extract version from '" << l << "'";});
}
- return pr.wait ();
+ return true;
}
catch (const process_error& e)
{
@@ -176,19 +185,30 @@ namespace bpkg
{
process pr (args, 0, -1); // Redirect STDOUT to a pipe.
- ifdstream is (pr.in_ofd);
- string l;
- getline (is, l);
+ try
+ {
+ ifdstream is (pr.in_ofd, fdstream_mode::skip);
- return l.compare (0, 5, "curl ") == 0 && pr.wait ();
+ string l;
+ getline (is, l);
+ is.close ();
+
+ return pr.wait () && l.compare (0, 5, "curl ") == 0;
+ }
+ catch (const ifdstream::failure&)
+ {
+ // Fall through.
+ }
}
catch (const process_error& e)
{
if (e.child ())
exit (1);
- return false;
+ // Fall through.
}
+
+ return false;
}
static process
@@ -276,19 +296,30 @@ namespace bpkg
{
process pr (args, 0, -1, 1); // Redirect STDOUT and STDERR to a pipe.
- ifdstream is (pr.in_ofd);
- string l;
- getline (is, l);
+ try
+ {
+ ifdstream is (pr.in_ofd, fdstream_mode::skip);
- return l.compare (0, 13, "usage: fetch ") == 0;
+ string l;
+ getline (is, l);
+ is.close ();
+
+ return pr.wait () && l.compare (0, 13, "usage: fetch ") == 0;
+ }
+ catch (const ifdstream::failure&)
+ {
+ // Fall through.
+ }
}
catch (const process_error& e)
{
if (e.child ())
exit (1);
- return false;
+ // Fall through.
}
+
+ return false;
}
static process
@@ -546,8 +577,7 @@ namespace bpkg
// calculation, then use the binary data to create the text stream for
// the manifest parsing.
//
- ifdstream is (pr.in_ofd, fdtranslate::binary);
- is.exceptions (ifdstream::badbit | ifdstream::failbit);
+ ifdstream is (pr.in_ofd, fdstream_mode::binary);
stringstream bs (ios::in | ios::out | ios::binary);
bs << is.rdbuf ();
@@ -604,18 +634,15 @@ namespace bpkg
try
{
- ifstream ifs (f.string (), ios::binary);
- if (!ifs.is_open ())
- fail << "unable to open " << f << " in read mode";
-
- auto_rm arm (r);
-
- ofstream ofs (r.string (), ios::binary);
- if (!ofs.is_open ())
- fail << "unable to open " << r << " in write mode";
+ // @@ Shouldn't we use cpfile() instead?
+ //
+ // @@ Yes, definitely.
+ //
+ ifdstream ifs (f, ios::binary);
- ifs.exceptions (ofstream::badbit | ofstream::failbit);
- ofs.exceptions (ofstream::badbit | ofstream::failbit);
+ auto_rm arm;
+ ofdstream ofs (r, ios::binary);
+ arm = auto_rm (r);
ofs << ifs.rdbuf ();
@@ -626,9 +653,9 @@ namespace bpkg
arm.cancel ();
}
- catch (const iostream::failure&)
+ catch (const ifdstream::failure& e)
{
- fail << "unable to copy " << f << " to " << r << ": io error";
+ fail << "unable to copy " << f << " to " << r << ": " << e.what ();
}
return r;
@@ -655,9 +682,7 @@ namespace bpkg
if (o != nullptr)
sha256sum = sha256 (*o, f); // Read file in the binary mode.
- ifstream ifs;
- ifs.exceptions (ofstream::badbit | ofstream::failbit);
- ifs.open (f.string ()); // Open file in the text mode.
+ ifdstream ifs (f); // Open file in the text mode.
manifest_parser mp (ifs, f.string ());
return make_pair (M (mp, ignore_unknown), move (sha256sum));
@@ -666,9 +691,9 @@ namespace bpkg
{
error (e.name, e.line, e.column) << e.description;
}
- catch (const ifstream::failure&)
+ catch (const ifdstream::failure& e)
{
- error << "unable to read from " << f;
+ error << "unable to read from " << f << ": " << e.what ();
}
throw failed ();
diff --git a/bpkg/help.cxx b/bpkg/help.cxx
index cf496ca..3d5efb8 100644
--- a/bpkg/help.cxx
+++ b/bpkg/help.cxx
@@ -50,10 +50,16 @@ namespace bpkg
//
return p.wait () ? 0 : 1;
}
+ // Catch ios_base::failure as std::system_error together with the
+ // pager-specific exceptions.
+ //
catch (const system_error& e)
{
error << "pager failed: " << e.what ();
- throw failed ();
+
+ // Fall through.
}
+
+ throw failed ();
}
}
diff --git a/bpkg/pkg-verify.cxx b/bpkg/pkg-verify.cxx
index 3c79cbd..ea072d9 100644
--- a/bpkg/pkg-verify.cxx
+++ b/bpkg/pkg-verify.cxx
@@ -4,8 +4,6 @@
#include <bpkg/pkg-verify>
-#include <fstream>
-
#include <butl/process>
#include <butl/fdstream>
@@ -38,11 +36,9 @@ namespace bpkg
//
process pr (start_extract (co, af, mf, diag));
- ifdstream is (pr.in_ofd);
- is.exceptions (ifdstream::badbit | ifdstream::failbit);
-
try
{
+ ifdstream is (pr.in_ofd, fdstream_mode::skip);
manifest_parser mp (is, mf.string ());
package_manifest m (mp, iu);
is.close ();
@@ -73,15 +69,6 @@ namespace bpkg
//
catch (const manifest_parsing& e)
{
- // Before we used to just close the file descriptor to signal to the
- // other end that we are not interested in the rest. But tar doesn't
- // take this very well (SIGPIPE). So now we are going to skip until
- // the end.
- //
- if (!is.eof ())
- is.ignore (numeric_limits<streamsize>::max ());
- is.close ();
-
if (pr.wait ())
{
if (diag)
@@ -93,8 +80,6 @@ namespace bpkg
}
catch (const ifdstream::failure&)
{
- is.close ();
-
if (pr.wait ())
{
if (diag)
@@ -144,10 +129,7 @@ namespace bpkg
try
{
- ifstream ifs;
- ifs.exceptions (ifstream::badbit | ifstream::failbit);
- ifs.open (mf.string ());
-
+ ifdstream ifs (mf);
manifest_parser mp (ifs, mf.string ());
package_manifest m (mp, iu);
@@ -175,10 +157,10 @@ namespace bpkg
throw failed ();
}
- catch (const ifstream::failure&)
+ catch (const ifdstream::failure& e)
{
if (diag)
- error << "unable to read from " << mf;
+ error << "unable to read from " << mf << ": " << e.what ();
throw failed ();
}
diff --git a/bpkg/rep-create.cxx b/bpkg/rep-create.cxx
index 61e3f81..16da164 100644
--- a/bpkg/rep-create.cxx
+++ b/bpkg/rep-create.cxx
@@ -5,9 +5,9 @@
#include <bpkg/rep-create>
#include <map>
-#include <fstream>
#include <iostream>
+#include <butl/fdstream>
#include <butl/filesystem> // dir_iterator
#include <bpkg/manifest>
@@ -217,17 +217,15 @@ namespace bpkg
try
{
{
- ofstream ofs;
- ofs.exceptions (ofstream::badbit | ofstream::failbit);
-
// While we can do nothing about repositories files edited on Windows
// and littered with the carriage return characters, there is no
// reason to litter the auto-generated packages and signature files.
//
- ofs.open (p.string (), ofstream::out | ofstream::binary);
+ ofdstream ofs (p, ios::binary);
manifest_serializer s (ofs, p.string ());
manifests.serialize (s);
+ ofs.close ();
}
const optional<string>& cert (rms.back ().certificate);
@@ -245,12 +243,11 @@ namespace bpkg
p = path (d / signature);
- ofstream ofs;
- ofs.exceptions (ofstream::badbit | ofstream::failbit);
- ofs.open (p.string (), ofstream::out | ofstream::binary);
+ ofdstream ofs (p, ios::binary);
manifest_serializer s (ofs, p.string ());
m.serialize (s);
+ ofs.close ();
}
else
{
@@ -266,9 +263,9 @@ namespace bpkg
{
fail << "unable to save manifest: " << e.description;
}
- catch (const ofstream::failure&)
+ catch (const ofdstream::failure& e)
{
- fail << "unable to write to " << p;
+ fail << "unable to write to " << p << ": " << e.what ();
}
if (verb)
diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx
index fb22986..d42ae6c 100644
--- a/bpkg/rep-fetch.cxx
+++ b/bpkg/rep-fetch.cxx
@@ -4,8 +4,6 @@
#include <bpkg/rep-fetch>
-#include <fstream>
-
#include <bpkg/manifest>
#include <bpkg/auth>