From b7763416f8a1e4940a10336d3a8b9fbbb879f414 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Mon, 12 Feb 2018 17:30:16 +0300 Subject: Clone and fetch git repositories --- bpkg/fetch.cxx | 263 +-------------------------------------------------------- 1 file changed, 2 insertions(+), 261 deletions(-) (limited to 'bpkg/fetch.cxx') 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 -#include - -#include #include -#include -#include -#include #include 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&, @@ -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 - static pair - 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 - static pair - 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 ( - nullptr, d / repositories, iu).first; - } - - pair - 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 (o, u, iu) - : fetch_manifest (&o, f, iu); - } - - static const path packages ("packages"); - - package_manifests - fetch_packages (const dir_path& d, bool iu) - { - return fetch_manifest (nullptr, d / packages, iu).first; - } - - pair - 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 (o, u, iu) - : fetch_manifest (&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 (o, u, iu).first - : fetch_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); - } } -- cgit v1.1