diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-10-10 17:48:03 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-10-10 17:48:03 +0200 |
commit | ddf8c2b62fa09eb765afc0c093d0d8908f7b69e4 (patch) | |
tree | 5956e674e0cb368061a9a9eb6d8bf742f96ffa75 /bpkg/pkg-fetch.cxx | |
parent | ec931aa6550b47461e92062a703e6ef9f4c24b17 (diff) |
Complete build command
Diffstat (limited to 'bpkg/pkg-fetch.cxx')
-rw-r--r-- | bpkg/pkg-fetch.cxx | 337 |
1 files changed, 198 insertions, 139 deletions
diff --git a/bpkg/pkg-fetch.cxx b/bpkg/pkg-fetch.cxx index fe8eca7..d2b0674 100644 --- a/bpkg/pkg-fetch.cxx +++ b/bpkg/pkg-fetch.cxx @@ -23,190 +23,249 @@ using namespace butl; namespace bpkg { - void - pkg_fetch (const pkg_fetch_options& o, cli::scanner& args) + + static shared_ptr<selected_package> + pkg_fetch (dir_path c, + transaction& t, + string n, + version v, + path a, + repository_location rl, + bool purge) { tracer trace ("pkg_fetch"); - dir_path c (o.directory ()); - level4 ([&]{trace << "configuration: " << c;}); - - database db (open (c, trace)); - transaction t (db.begin ()); - session s; + database& db (t.database ()); + tracer_guard tg (db, trace); - path a; - auto_rm arm; - bool purge; - repository_location rl; - shared_ptr<selected_package> sp; - - // Check if the package already exists in this configuration and - // diagnose all the illegal cases. We want to do this as soon as - // the package name is known which happens at different times - // depending on whether we are dealing with an existing archive - // or fetching one. + // Make the archive and configuration paths absolute and normalized. + // If the archive is inside the configuration, use the relative path. + // This way we can move the configuration around. // - auto check = [&o, &c, &db] (const string& n) - -> shared_ptr<selected_package> - { - shared_ptr<selected_package> p (db.find<selected_package> (n)); - - if (p != nullptr) - { - bool s (p->state == package_state::fetched || - p->state == package_state::unpacked); - - if (!o.replace () || !s) - { - diag_record dr (fail); - - dr << "package " << n << " already exists in configuration " << c << - info << "version: " << p->version << ", state: " << p->state; - - if (s) // Suitable state for replace? - dr << info << "use 'pkg-fetch --replace|-r' to replace"; - } - } + c.complete ().normalize (); + a.complete ().normalize (); - return p; - }; + if (a.sub (c)) + a = a.leaf (c); - if (o.existing ()) + shared_ptr<selected_package> p (db.find<selected_package> (n)); + if (p != nullptr) { - if (!args.more ()) - fail << "archive path argument expected" << - info << "run 'bpkg help pkg-fetch' for more information"; - - a = path (args.next ()); - - if (!exists (a)) - fail << "archive file '" << a << "' does not exist"; + // Clean up the source directory and archive of the package we are + // replacing. Once this is done, there is no going back. If things + // go badly, we can't simply abort the transaction. + // + pkg_purge_fs (c, t, p); - purge = o.purge (); + p->version = move (v); + p->state = package_state::fetched; + p->repository = move (rl); + p->archive = move (a); + p->purge_archive = purge; - // Use the special root repository as the repository of this - // package. - // - rl = repository_location (); + db.update (p); } else { - if (!args.more ()) - fail << "package name/version argument expected" << - info << "run 'bpkg help pkg-fetch' for more information"; - - const char* arg (args.next ()); - string n (parse_package_name (arg)); - version v (parse_package_version (arg)); - - if (v.empty ()) - fail << "package version expected" << - info << "run 'bpkg help pkg-fetch' for more information"; - - // Check/diagnose an already existing package. + // Add the package to the configuration. // - sp = check (n); + p.reset (new selected_package { + move (n), + move (v), + package_state::fetched, + move (rl), + move (a), + purge, + nullopt, // No source directory yet. + false, + nullopt, // No output directory yet. + {}}); // No prerequisites captured yet. - if (db.query_value<repository_count> () == 0) - fail << "configuration " << c << " has no repositories" << - info << "use 'bpkg rep-add' to add a repository"; + db.persist (p); + } - if (db.query_value<available_package_count> () == 0) - fail << "configuration " << c << " has no available packages" << - info << "use 'bpkg rep-fetch' to fetch available packages list"; + t.commit (); + return p; + } - shared_ptr<available_package> ap ( - db.find<available_package> (available_package_id (n, v))); + // Check if the package already exists in this configuration and + // diagnose all the illegal cases. We want to do this as soon as + // the package name is known which happens at different times + // depending on whether we are dealing with an existing archive + // or fetching one. + // + static void + pkg_fetch_check (const dir_path& c, + transaction& t, + const string& n, + bool replace) + { + tracer trace ("pkg_fetch_check"); - if (ap == nullptr) - fail << "package " << n << " " << v << " is not available"; + database& db (t.database ()); + tracer_guard tg (db, trace); - // Pick a repository. Preferring a local one over the remotes seems - // like a sensible thing to do. - // - const package_location* pl (&ap->locations.front ()); + if (shared_ptr<selected_package> p = db.find<selected_package> (n)) + { + bool s (p->state == package_state::fetched || + p->state == package_state::unpacked); - for (const package_location& l: ap->locations) + if (!replace || !s) { - if (!l.repository.load ()->location.remote ()) - { - pl = &l; - break; - } - } + diag_record dr (fail); - if (verb > 1) - text << "fetching " << pl->location.leaf () << " " - << "from " << pl->repository->name; + dr << "package " << n << " already exists in configuration " << c << + info << "version: " << p->version << ", state: " << p->state; - rl = pl->repository->location; - a = fetch_archive (o, rl, pl->location, c); - arm = auto_rm (a); - purge = true; + if (s) // Suitable state for replace? + dr << info << "use 'pkg-fetch --replace|-r' to replace"; + } } + } - level4 ([&]{trace << "package archive: " << a << ", purge: " << purge;}); + shared_ptr<selected_package> + pkg_fetch (const common_options& co, + const dir_path& c, + transaction& t, + path a, + bool replace, + bool purge) + { + tracer trace ("pkg_fetch"); + + if (!exists (a)) + fail << "archive file '" << a << "' does not exist"; + + level4 ([&]{trace << "archive: " << a << ", purge: " << purge;}); // Verify archive is a package and get its manifest. // - package_manifest m (pkg_verify (o, a)); + package_manifest m (pkg_verify (co, a)); level4 ([&]{trace << m.name << " " << m.version;}); // Check/diagnose an already existing package. // - if (o.existing ()) - sp = check (m.name); + pkg_fetch_check (c, t, m.name, replace); - // Make the archive and configuration paths absolute and normalized. - // If the archive is inside the configuration, use the relative path. - // This way we can move the configuration around. + // Use the special root repository as the repository of this + // package. // - c.complete ().normalize (); - a.complete ().normalize (); + return pkg_fetch (c, + t, + move (m.name), + move (m.version), + move (a), + repository_location (), + purge); + } - if (a.sub (c)) - a = a.leaf (c); + shared_ptr<selected_package> + pkg_fetch (const common_options& co, + const dir_path& c, + transaction& t, + string n, + version v, + bool replace) + { + tracer trace ("pkg_fetch"); + + database& db (t.database ()); + tracer_guard tg (db, trace); + + // Check/diagnose an already existing package. + // + pkg_fetch_check (c, t, n, replace); + + if (db.query_value<repository_count> () == 0) + fail << "configuration " << c << " has no repositories" << + info << "use 'bpkg rep-add' to add a repository"; + + if (db.query_value<available_package_count> () == 0) + fail << "configuration " << c << " has no available packages" << + info << "use 'bpkg rep-fetch' to fetch available packages list"; + + shared_ptr<available_package> ap ( + db.find<available_package> (available_package_id (n, v))); + + if (ap == nullptr) + fail << "package " << n << " " << v << " is not available"; - if (sp != nullptr) + // Pick a repository. Preferring a local one over the remotes seems + // like a sensible thing to do. + // + const package_location* pl (&ap->locations.front ()); + + for (const package_location& l: ap->locations) { - // Clean up the source directory and archive of the package we are - // replacing. Once this is done, there is no going back. If things - // go badly, we can't simply abort the transaction. - // - pkg_purge_fs (c, t, sp); + if (!l.repository.load ()->location.remote ()) + { + pl = &l; + break; + } + } + + if (verb > 1) + text << "fetching " << pl->location.leaf () << " " + << "from " << pl->repository->name; + + path a (fetch_archive (co, pl->repository->location, pl->location, c)); + auto_rm arm (a); + + shared_ptr<selected_package> p ( + pkg_fetch (c, + t, + move (n), + move (v), + move (a), + pl->repository->location, + true)); // Purge. + + arm.cancel (); + return p; + } + + void + pkg_fetch (const pkg_fetch_options& o, cli::scanner& args) + { + tracer trace ("pkg_fetch"); + + dir_path c (o.directory ()); + level4 ([&]{trace << "configuration: " << c;}); + + database db (open (c, trace)); + transaction t (db.begin ()); + session s; - sp->version = move (m.version); - sp->state = package_state::fetched; - sp->repository = move (rl); - sp->archive = move (a); - sp->purge_archive = purge; + shared_ptr<selected_package> p; + + // pkg_fetch() in both cases commits the transaction. + // + if (o.existing ()) + { + if (!args.more ()) + fail << "archive path argument expected" << + info << "run 'bpkg help pkg-fetch' for more information"; - db.update (sp); + p = pkg_fetch (o, c, t, path (args.next ()), o.replace (), o.purge ()); } else { - // Add the package to the configuration. - // - sp.reset (new selected_package { - move (m.name), - move (m.version), - package_state::fetched, - move (rl), - move (a), - purge, - nullopt, // No source directory yet. - false, - nullopt, // No output directory yet. - {}}); // No prerequisites captured yet. + if (!args.more ()) + fail << "package name/version argument expected" << + info << "run 'bpkg help pkg-fetch' for more information"; - db.persist (sp); - } + const char* arg (args.next ()); + string n (parse_package_name (arg)); + version v (parse_package_version (arg)); - t.commit (); - arm.cancel (); + if (v.empty ()) + fail << "package version expected" << + info << "run 'bpkg help pkg-fetch' for more information"; + + p = pkg_fetch (o, c, t, move (n), move (v), o.replace ()); + } if (verb) - text << "fetched " << sp->name << " " << sp->version; + text << "fetched " << p->name << " " << p->version; } } |