aboutsummaryrefslogtreecommitdiff
path: root/bpkg/fetch.cxx
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2018-02-12 17:30:16 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2018-02-12 17:34:55 +0300
commitb7763416f8a1e4940a10336d3a8b9fbbb879f414 (patch)
tree31f1bc7427181aa81984a639d998ca4e99058199 /bpkg/fetch.cxx
parentecb1efeebaa5597bee4cfdaab7bff4007b73127d (diff)
Clone and fetch git repositories
Diffstat (limited to 'bpkg/fetch.cxx')
-rw-r--r--bpkg/fetch.cxx263
1 files changed, 2 insertions, 261 deletions
diff --git a/bpkg/fetch.cxx b/bpkg/fetch.cxx
index 5464c4a..c5366e3 100644
--- a/bpkg/fetch.cxx
+++ b/bpkg/fetch.cxx
@@ -4,14 +4,8 @@
#include <bpkg/fetch.hxx>
-#include <sstream>
-
-#include <libbutl/process.mxx>
#include <libbutl/fdstream.mxx>
-#include <libbutl/filesystem.mxx>
-#include <libbutl/manifest-parser.mxx>
-#include <bpkg/checksum.hxx>
#include <bpkg/diagnostics.hxx>
using namespace std;
@@ -510,11 +504,8 @@ namespace bpkg
return fetch_kind;
}
- // If out is empty, then fetch to STDOUT. In this case also don't
- // show any progress unless we are running verbose.
- //
- static process
- start (const common_options& o, const string& url, const path& out = path ())
+ process
+ start_fetch (const common_options& o, const string& url, const path& out)
{
process (*f) (const path&,
const optional<size_t>&,
@@ -547,254 +538,4 @@ namespace bpkg
throw failed ();
}
}
-
- static path
- fetch_file (const common_options& o,
- const repository_url& u,
- const dir_path& d)
- {
- path r (d / u.path->leaf ());
-
- if (exists (r))
- fail << "file " << r << " already exists";
-
- auto_rmfile arm (r);
- process pr (start (o, u.string (), r));
-
- if (!pr.wait ())
- {
- // 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";
- }
-
- arm.cancel ();
- return r;
- }
-
- template <typename M>
- static pair<M, string/*checksum*/>
- fetch_manifest (const common_options& o,
- const repository_url& u,
- bool ignore_unknown)
- {
- string url (u.string ());
- process pr (start (o, url));
-
- try
- {
- // Unfortunately we cannot read from the original source twice as we do
- // below for files. There doesn't seem to be anything better than reading
- // the entire file into memory and then streaming it twice, once to
- // calculate the checksum and the second time to actually parse. We need
- // to read the original stream in the binary mode for the checksum
- // calculation, then use the binary data to create the text stream for
- // the manifest parsing.
- //
- ifdstream is (move (pr.in_ofd), fdstream_mode::binary);
- stringstream bs (ios::in | ios::out | ios::binary);
-
- // Note that the eof check is important: if the stream is at eof, write
- // will fail.
- //
- if (is.peek () != ifdstream::traits_type::eof ())
- bs << is.rdbuf ();
-
- is.close ();
-
- string s (bs.str ());
- string sha256sum (sha256 (s.c_str (), s.size ()));
-
- istringstream ts (s); // Text mode.
-
- manifest_parser mp (ts, url);
- M m (mp, ignore_unknown);
-
- if (pr.wait ())
- return make_pair (move (m), move (sha256sum));
-
- // Child existed 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.
- //
- catch (const manifest_parsing& e)
- {
- if (pr.wait ())
- fail (e.name, e.line, e.column) << e.description;
- }
- catch (const io_error&)
- {
- if (pr.wait ())
- fail << "unable to read fetched " << url;
- }
-
- // We should only get here if the child exited with an error status.
- //
- assert (!pr.wait ());
-
- // While it is reasonable to assuming the child process issued
- // diagnostics, some may not mention the URL.
- //
- fail << "unable to fetch " << url <<
- info << "re-run with -v for more information" << endf;
- }
-
- static path
- fetch_file (const path& f, const dir_path& d)
- {
- path r (d / f.leaf ());
-
- try
- {
- cpfile (f, r);
- }
- catch (const system_error& e)
- {
- fail << "unable to copy " << f << " to " << r << ": " << e;
- }
-
- return r;
- }
-
- // If o is nullptr, then don't calculate the checksum.
- //
- template <typename M>
- static pair<M, string/*checksum*/>
- fetch_manifest (const common_options* o,
- const path& f,
- bool ignore_unknown)
- {
- if (!exists (f))
- fail << "file " << f << " does not exist";
-
- try
- {
- // We can not use the same file stream for both calculating the checksum
- // and reading the manifest. The file should be opened in the binary
- // mode for the first operation and in the text mode for the second one.
- //
- string sha256sum;
- if (o != nullptr)
- sha256sum = sha256 (*o, f); // Read file in the binary 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));
- }
- catch (const manifest_parsing& e)
- {
- fail (e.name, e.line, e.column) << e.description << endf;
- }
- catch (const io_error& e)
- {
- fail << "unable to read from " << f << ": " << e << endf;
- }
- }
-
- static const path repositories ("repositories");
-
- repository_manifests
- fetch_repositories (const dir_path& d, bool iu)
- {
- return fetch_manifest<repository_manifests> (
- nullptr, d / repositories, iu).first;
- }
-
- pair<repository_manifests, string/*checksum*/>
- fetch_repositories (const common_options& o,
- const repository_location& rl,
- bool iu)
- {
- assert (rl.remote () || rl.absolute ());
-
- repository_url u (rl.url ());
-
- path& f (*u.path);
- f /= repositories;
-
- return rl.remote ()
- ? fetch_manifest<repository_manifests> (o, u, iu)
- : fetch_manifest<repository_manifests> (&o, f, iu);
- }
-
- static const path packages ("packages");
-
- package_manifests
- fetch_packages (const dir_path& d, bool iu)
- {
- return fetch_manifest<package_manifests> (nullptr, d / packages, iu).first;
- }
-
- pair<package_manifests, string/*checksum*/>
- fetch_packages (const common_options& o,
- const repository_location& rl,
- bool iu)
- {
- assert (rl.remote () || rl.absolute ());
-
- repository_url u (rl.url ());
-
- path& f (*u.path);
- f /= packages;
-
- return rl.remote ()
- ? fetch_manifest<package_manifests> (o, u, iu)
- : fetch_manifest<package_manifests> (&o, f, iu);
- }
-
- static const path signature ("signature");
-
- signature_manifest
- fetch_signature (const common_options& o,
- const repository_location& rl,
- bool iu)
- {
- assert (rl.remote () || rl.absolute ());
-
- repository_url u (rl.url ());
-
- path& f (*u.path);
- f /= signature;
-
- return rl.remote ()
- ? fetch_manifest<signature_manifest> (o, u, iu).first
- : fetch_manifest<signature_manifest> (nullptr, f, iu).first;
- }
-
- path
- fetch_archive (const common_options& o,
- const repository_location& rl,
- const path& a,
- const dir_path& d)
- {
- assert (!a.empty () && a.relative ());
- assert (rl.remote () || rl.absolute ());
-
- repository_url u (rl.url ());
-
- path& f (*u.path);
- f /= a;
-
- auto bad_loc = [&u] () {fail << "invalid archive location " << u;};
-
- try
- {
- f.normalize ();
-
- if (*f.begin () == "..") // Can be the case for the remote location.
- bad_loc ();
- }
- catch (const invalid_path&)
- {
- bad_loc ();
- }
-
- return rl.remote ()
- ? fetch_file (o, u, d)
- : fetch_file (f, d);
- }
}