aboutsummaryrefslogtreecommitdiff
path: root/bpkg/fetch-pkg.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2023-07-21 20:19:15 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2023-07-25 17:09:35 +0300
commitfd4439e4d067f77642b3f3dfcaf50d605e69235f (patch)
treee72cabbd3e931021a8ccbf80943fb6d9cc8531b6 /bpkg/fetch-pkg.cxx
parent8468f0beac9b792d7e2621f1a78a485ed542fb1d (diff)
Advice user to re-fetch repositories if package fetch ends up with 404 HTTP status code (GH issue #299)
Diffstat (limited to 'bpkg/fetch-pkg.cxx')
-rw-r--r--bpkg/fetch-pkg.cxx76
1 files changed, 68 insertions, 8 deletions
diff --git a/bpkg/fetch-pkg.cxx b/bpkg/fetch-pkg.cxx
index ca4767f..721e4b8 100644
--- a/bpkg/fetch-pkg.cxx
+++ b/bpkg/fetch-pkg.cxx
@@ -97,20 +97,80 @@ namespace bpkg
if (exists (df))
fail << "file " << df << " already exists";
+ // Currently we only expect fetching a package archive via the HTTP(S)
+ // protocol.
+ //
+ switch (u.scheme)
+ {
+ case repository_protocol::git:
+ case repository_protocol::ssh:
+ case repository_protocol::file: assert (false);
+ case repository_protocol::http:
+ case repository_protocol::https: break;
+ }
+
auto_rmfile arm (df);
- process pr (start_fetch (o,
- u.string (),
- df,
- string () /* user_agent */,
- o.pkg_proxy ()));
- if (!pr.wait ())
+ // Note that a package file may not be present in the repository due to
+ // outdated repository information. Thus, while fetching the file we also
+ // try to retrieve the HTTP status code. If the HTTP status code is
+ // retrieved and is 404 (not found) or the fetch program doesn't support
+ // its retrieval and fails, then we also advise the user to re-fetch the
+ // repositories.
+ //
+ pair<process, uint16_t> ps (
+ start_fetch_http (o,
+ u.string (),
+ df,
+ string () /* user_agent */,
+ o.pkg_proxy ()));
+
+ process& pr (ps.first);
+ uint16_t sc (ps.second);
+
+ // Fail if the fetch process didn't exit normally with 0 code or the HTTP
+ // status code is retrieved and differs from 200.
+ //
+ // Note that the diagnostics may potentially look as follows:
+ //
+ // foo-1.0.0.tar.gz:
+ // ###################################################### 100.0%
+ // error: unable to fetch package https://example.org/1/foo-1.0.0.tar.gz
+ // info: repository metadata could be stale
+ // info: run 'bpkg rep-fetch' (or equivalent) to update
+ //
+ // It's a bit unfortunate that the 100% progress indicator can be shown
+ // for a potential HTTP error and it doesn't seem that we can easily fix
+ // that. Note, however, that this situation is not very common and
+ // probably that's fine.
+ //
+ if (!pr.wait () || (sc != 0 && sc != 200))
{
// While it is reasonable to assuming the child process issued
// diagnostics, some may not mention the URL.
//
- fail << "unable to fetch " << u <<
- info << "re-run with -v for more information";
+ diag_record dr (fail);
+ dr << "unable to fetch package " << u;
+
+ // Print the HTTP status code in the diagnostics on the request failure,
+ // unless it cannot be retrieved or is 404. Note that the fetch program
+ // may even exit successfully on such a failure (see start_fetch_http()
+ // for details) and issue no diagnostics at all.
+ //
+ if (sc != 0 && sc != 200 && sc != 404)
+ dr << info << "HTTP status code " << sc;
+
+ // If not found, advise the user to re-fetch the repositories. Note that
+ // if the status code cannot be retrieved, we assume it could be 404 and
+ // advise.
+ //
+ if (sc == 404 || sc == 0)
+ {
+ dr << info << "repository metadata could be stale" <<
+ info << "run 'bpkg rep-fetch' (or equivalent) to update";
+ }
+ else if (verb < 2)
+ dr << info << "re-run with -v for more information";
}
arm.cancel ();