aboutsummaryrefslogtreecommitdiff
path: root/bpkg/pkg-fetch.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-10-10 17:48:03 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-10-10 17:48:03 +0200
commitddf8c2b62fa09eb765afc0c093d0d8908f7b69e4 (patch)
tree5956e674e0cb368061a9a9eb6d8bf742f96ffa75 /bpkg/pkg-fetch.cxx
parentec931aa6550b47461e92062a703e6ef9f4c24b17 (diff)
Complete build command
Diffstat (limited to 'bpkg/pkg-fetch.cxx')
-rw-r--r--bpkg/pkg-fetch.cxx337
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;
}
}