aboutsummaryrefslogtreecommitdiff
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
parentec931aa6550b47461e92062a703e6ef9f4c24b17 (diff)
Complete build command
-rw-r--r--bpkg/build.cxx147
-rw-r--r--bpkg/pkg-command6
-rw-r--r--bpkg/pkg-command.cxx35
-rw-r--r--bpkg/pkg-configure9
-rw-r--r--bpkg/pkg-configure.cxx95
-rw-r--r--bpkg/pkg-fetch23
-rw-r--r--bpkg/pkg-fetch.cxx337
-rw-r--r--bpkg/pkg-purge.cxx4
-rw-r--r--bpkg/pkg-unpack18
-rw-r--r--bpkg/pkg-unpack.cxx26
-rw-r--r--bpkg/pkg-update8
-rwxr-xr-xbpkg/test.sh1
12 files changed, 492 insertions, 217 deletions
diff --git a/bpkg/build.cxx b/bpkg/build.cxx
index 1345fbf..eda1199 100644
--- a/bpkg/build.cxx
+++ b/bpkg/build.cxx
@@ -23,7 +23,11 @@
#include <bpkg/common-options>
+#include <bpkg/pkg-fetch>
+#include <bpkg/pkg-unpack>
+#include <bpkg/pkg-update>
#include <bpkg/pkg-verify>
+#include <bpkg/pkg-configure>
#include <bpkg/pkg-disfigure>
using namespace std;
@@ -35,6 +39,7 @@ namespace bpkg
//
// - User-selected vs auto-selected packages.
// - Detect and complain about dependency cycles.
+ // - Configuration vars (both passed and preserved)
//
// Try to find a package that optionally satisfies the specified
@@ -205,17 +210,16 @@ namespace bpkg
struct satisfied_packages
{
- using list_type = list<reference_wrapper<const satisfied_package>>;
+ using list_type = list<reference_wrapper<satisfied_package>>;
using iterator = list_type::iterator;
- using const_iterator = list_type::const_iterator;
- using const_reverse_iterator = list_type::const_reverse_iterator;
+ using reverse_iterator = list_type::reverse_iterator;
- const_iterator begin () const {return list_.begin ();}
- const_iterator end () const {return list_.end ();}
+ iterator begin () {return list_.begin ();}
+ iterator end () {return list_.end ();}
- const_reverse_iterator rbegin () const {return list_.rbegin ();}
- const_reverse_iterator rend () const {return list_.rend ();}
+ reverse_iterator rbegin () {return list_.rbegin ();}
+ reverse_iterator rend () {return list_.rend ();}
// Collect the package. Return true if this package version was,
// in fact, added to the map and false if it was already there
@@ -519,7 +523,7 @@ namespace bpkg
// position of its "earliest" prerequisite -- this is where it
// will be inserted.
//
- const satisfied_package& p (mi->second.package);
+ satisfied_package& p (mi->second.package);
const shared_ptr<selected_package>& sp (p.selected);
const shared_ptr<available_package>& ap (p.available);
@@ -995,17 +999,21 @@ namespace bpkg
return;
// Ok, we have the green light. The overall action plan is as follows.
- // Note that for some actions, e.g., drop or fetch, the order is not
- // really important. We will, however, do it right to left since that
- // is the order closest to that of the user selection.
//
// 1. disfigure up/down-graded, reconfigured [left to right]
- // 2. drop up/down-graded
+ // 2. purge up/down-graded
// 3. fetch new, up/down-graded
// 4. unpack new, up/down-graded
// 5. configure all [right to left]
// 6. build user selection [right to left]
//
+ // Note that for some actions, e.g., purge or fetch, the order is not
+ // really important. We will, however, do it right to left since that
+ // is the order closest to that of the user selection.
+ //
+ // We are also going to combine purge/fetch/unpack into a single step
+ // and use the replace mode so it will become just fetch/unpack.
+ //
// disfigure
//
@@ -1029,5 +1037,120 @@ namespace bpkg
if (verb)
text << "disfigured " << sp->name << " " << sp->version;
}
+
+ // fetch/unpack
+ //
+ for (satisfied_package& p: reverse_iterate (pkgs))
+ {
+ shared_ptr<selected_package>& sp (p.selected);
+ const shared_ptr<available_package>& ap (p.available);
+
+ if (ap == nullptr) // Skip dependents.
+ continue;
+
+ // Fetch if this is a new package or if we are up/down-grading.
+ //
+ if (sp == nullptr || sp->version != ap->version)
+ {
+ sp.reset (); // For the directory case below.
+
+ // Distinguish between the package and archive/directory cases.
+ //
+ const package_location& pl (ap->locations[0]); // Got to have one.
+
+ if (pl.repository.object_id () != "") // Special root?
+ {
+ transaction t (db.begin ());
+ sp = pkg_fetch (o,
+ c,
+ t,
+ ap->id.name,
+ ap->version,
+ true); // Replace; commits the transaction.
+ }
+ else if (exists (pl.location)) // Directory case is handled by unpack.
+ {
+ transaction t (db.begin ());
+ sp = pkg_fetch (o,
+ c,
+ t,
+ pl.location, // Archive path.
+ true, // Replace
+ false); // Don't purge; commits the transaction.
+ }
+
+ if (sp != nullptr) // Actually unpacked something?
+ {
+ assert (sp->state == package_state::fetched);
+
+ if (verb)
+ text << "fetched " << sp->name << " " << sp->version;
+ }
+ }
+
+ // Unpack. Note that the package can still be NULL if this is the
+ // directory case (see the fetch code above).
+ //
+ if (sp == nullptr || sp->state == package_state::fetched)
+ {
+ if (sp != nullptr)
+ {
+ transaction t (db.begin ());
+ sp = pkg_unpack (o, c, t, ap->id.name); // Commits the transaction.
+ }
+ else
+ {
+ const package_location& pl (ap->locations[0]);
+ assert (pl.repository.object_id () == ""); // Special root.
+
+ transaction t (db.begin ());
+ sp = pkg_unpack (c,
+ t,
+ path_cast<dir_path> (pl.location),
+ true, // Replace.
+ false); // Don't purge; commits the transaction.
+ }
+
+ assert (sp->state == package_state::unpacked);
+
+ if (verb)
+ text << "unpacked " << sp->name << " " << sp->version;
+ }
+ }
+
+ // configure
+ //
+ for (const satisfied_package& p: reverse_iterate (pkgs))
+ {
+ const shared_ptr<selected_package>& sp (p.selected);
+
+ assert (sp != nullptr);
+
+ // We configure everything that isn't already configured.
+ //
+ if (sp->state == package_state::configured)
+ continue;
+
+ transaction t (db.begin ());
+ pkg_configure (c, t, sp, strings ()); // Commits the transaction.
+ assert (sp->state == package_state::configured);
+
+ if (verb)
+ text << "configured " << sp->name << " " << sp->version;
+ }
+
+ // update
+ //
+ for (const satisfied_package& p: reverse_iterate (pkgs))
+ {
+ const shared_ptr<selected_package>& sp (p.selected);
+
+ // @@ TODO: update user selection only.
+ //
+ pkg_update (c, sp);
+
+ if (verb)
+ text << "updated " << sp->name << " " << sp->version;
+ }
}
}
diff --git a/bpkg/pkg-command b/bpkg/pkg-command
index 0628a06..360a550 100644
--- a/bpkg/pkg-command
+++ b/bpkg/pkg-command
@@ -6,6 +6,7 @@
#define BPKG_PKG_COMMAND
#include <bpkg/types>
+#include <bpkg/forward> // selected_package
#include <bpkg/configuration-options>
namespace bpkg
@@ -16,6 +17,11 @@ namespace bpkg
pkg_command (const string& cmd, // Without the 'pkg-' prefix.
const configuration_options&,
cli::scanner& args);
+
+ void
+ pkg_command (const string& cmd,
+ const dir_path& configuration,
+ const shared_ptr<selected_package>&);
}
#endif // BPKG_PKG_COMMAND
diff --git a/bpkg/pkg-command.cxx b/bpkg/pkg-command.cxx
index 39caa8e..67ea07a 100644
--- a/bpkg/pkg-command.cxx
+++ b/bpkg/pkg-command.cxx
@@ -18,11 +18,33 @@ namespace bpkg
{
void
pkg_command (const string& cmd,
+ const dir_path& c,
+ const shared_ptr<selected_package>& p)
+ {
+ tracer trace ("pkg_command");
+
+ assert (p->state == package_state::configured);
+ assert (p->out_root); // Should be present since configured.
+
+ level4 ([&]{trace << "command: " << cmd;});
+
+ dir_path out_root (c / *p->out_root); // Always relative.
+ level4 ([&]{trace << "out_root: " << out_root;});
+
+ // Form the buildspec.
+ //
+ string bspec (cmd + "(" + out_root.string () + "/)");
+ level4 ([&]{trace << "buildspec: " << bspec;});
+
+ run_b (bspec);
+ }
+
+ void
+ pkg_command (const string& cmd,
const configuration_options& o,
cli::scanner& args)
{
tracer trace ("pkg_command");
- level4 ([&]{trace << "command: " << cmd;});
const dir_path& c (o.directory ());
level4 ([&]{trace << "configuration: " << c;});
@@ -48,16 +70,7 @@ namespace bpkg
level4 ([&]{trace << p->name << " " << p->version;});
- assert (p->out_root); // Should be present since configured.
- dir_path out_root (c / *p->out_root); // Always relative.
- level4 ([&]{trace << "out_root: " << out_root;});
-
- // Form the buildspec.
- //
- string bspec (cmd + "(" + out_root.string () + "/)");
- level4 ([&]{trace << "buildspec: " << bspec;});
-
- run_b (bspec);
+ pkg_command (cmd, c, p);
if (verb)
text << cmd << (cmd.back () != 'e' ? "ed " : "d ")
diff --git a/bpkg/pkg-configure b/bpkg/pkg-configure
index e314e52..b042e60 100644
--- a/bpkg/pkg-configure
+++ b/bpkg/pkg-configure
@@ -6,12 +6,21 @@
#define BPKG_PKG_CONFIGURE
#include <bpkg/types>
+#include <bpkg/forward> // transaction, selected_package
#include <bpkg/pkg-configure-options>
namespace bpkg
{
void
pkg_configure (const pkg_configure_options&, cli::scanner& args);
+
+ // Configure the package, update its state, and commit the transaction.
+ //
+ void
+ pkg_configure (const dir_path& configuration,
+ transaction&,
+ const shared_ptr<selected_package>&,
+ const strings& config_vars);
}
#endif // BPKG_PKG_CONFIGURE
diff --git a/bpkg/pkg-configure.cxx b/bpkg/pkg-configure.cxx
index c76fae9..9e256ce 100644
--- a/bpkg/pkg-configure.cxx
+++ b/bpkg/pkg-configure.cxx
@@ -21,53 +21,21 @@ using namespace butl;
namespace bpkg
{
void
- pkg_configure (const pkg_configure_options& o, cli::scanner& args)
+ pkg_configure (const dir_path& c,
+ transaction& t,
+ const shared_ptr<selected_package>& p,
+ const strings& vars)
{
tracer trace ("pkg_configure");
- const dir_path& c (o.directory ());
- level4 ([&]{trace << "configuration: " << c;});
-
- // Sort arguments into the package name and configuration variables.
- //
- string n;
- strings vars;
-
- while (args.more ())
- {
- string a (args.next ());
-
- if (a.find ('=') != string::npos)
- vars.push_back (move (a));
- else if (n.empty ())
- n = move (a);
- else
- fail << "unexpected argument '" << a << "'";
- }
-
- if (n.empty ())
- fail << "package name argument expected" <<
- info << "run 'bpkg help pkg-configure' for more information";
-
- database db (open (c, trace));
- transaction t (db.begin ());
- session s;
-
- shared_ptr<selected_package> p (db.find<selected_package> (n));
-
- if (p == nullptr)
- fail << "package " << n << " does not exist in configuration " << c;
-
- if (p->state != package_state::unpacked)
- fail << "package " << n << " is " << p->state <<
- info << "expected it to be unpacked";
+ assert (p->state == package_state::unpacked);
+ assert (p->src_root); // Must be set since unpacked.
- level4 ([&]{trace << p->name << " " << p->version;});
+ database& db (t.database ());
+ tracer_guard tg (db, trace);
// Calculate package's src_root and out_root.
//
- assert (p->src_root); // Must be set since unpacked.
-
dir_path src_root (p->src_root->absolute ()
? *p->src_root
: c / *p->src_root);
@@ -174,6 +142,53 @@ namespace bpkg
db.update (p);
t.commit ();
+ }
+
+ void
+ pkg_configure (const pkg_configure_options& o, cli::scanner& args)
+ {
+ tracer trace ("pkg_configure");
+
+ const dir_path& c (o.directory ());
+ level4 ([&]{trace << "configuration: " << c;});
+
+ // Sort arguments into the package name and configuration variables.
+ //
+ string n;
+ strings vars;
+
+ while (args.more ())
+ {
+ string a (args.next ());
+
+ if (a.find ('=') != string::npos)
+ vars.push_back (move (a));
+ else if (n.empty ())
+ n = move (a);
+ else
+ fail << "unexpected argument '" << a << "'";
+ }
+
+ if (n.empty ())
+ fail << "package name argument expected" <<
+ info << "run 'bpkg help pkg-configure' for more information";
+
+ database db (open (c, trace));
+ transaction t (db.begin ());
+ session s;
+
+ shared_ptr<selected_package> p (db.find<selected_package> (n));
+
+ if (p == nullptr)
+ fail << "package " << n << " does not exist in configuration " << c;
+
+ if (p->state != package_state::unpacked)
+ fail << "package " << n << " is " << p->state <<
+ info << "expected it to be unpacked";
+
+ level4 ([&]{trace << p->name << " " << p->version;});
+
+ pkg_configure (c, t, p, vars); // Commits the transaction.
if (verb)
text << "configured " << p->name << " " << p->version;
diff --git a/bpkg/pkg-fetch b/bpkg/pkg-fetch
index 1f25c82..7cfd214 100644
--- a/bpkg/pkg-fetch
+++ b/bpkg/pkg-fetch
@@ -5,13 +5,36 @@
#ifndef BPKG_PKG_FETCH
#define BPKG_PKG_FETCH
+#include <bpkg/manifest> // version
+
#include <bpkg/types>
+#include <bpkg/forward> // transaction, selected_package
#include <bpkg/pkg-fetch-options>
namespace bpkg
{
void
pkg_fetch (const pkg_fetch_options&, cli::scanner& args);
+
+ // Fetch the package as an archive file and commit the transaction.
+ //
+ shared_ptr<selected_package>
+ pkg_fetch (const common_options&,
+ const dir_path& configuration,
+ transaction&,
+ path archive,
+ bool replace,
+ bool purge);
+
+ // Fetch the package from a repository and commit the transaction.
+ //
+ shared_ptr<selected_package>
+ pkg_fetch (const common_options&,
+ const dir_path& configuration,
+ transaction&,
+ string name,
+ version,
+ bool replace);
}
#endif // BPKG_PKG_FETCH
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;
}
}
diff --git a/bpkg/pkg-purge.cxx b/bpkg/pkg-purge.cxx
index dd92857..b13eabd 100644
--- a/bpkg/pkg-purge.cxx
+++ b/bpkg/pkg-purge.cxx
@@ -22,11 +22,11 @@ namespace bpkg
const shared_ptr<selected_package>& p,
bool archive)
{
+ tracer trace ("pkg_purge_archive");
+
assert (p->state == package_state::fetched ||
p->state == package_state::unpacked);
- tracer trace ("pkg_purge_archive");
-
database& db (t.database ());
tracer_guard tg (db, trace);
diff --git a/bpkg/pkg-unpack b/bpkg/pkg-unpack
index 4a37c35..a569efe 100644
--- a/bpkg/pkg-unpack
+++ b/bpkg/pkg-unpack
@@ -6,12 +6,30 @@
#define BPKG_PKG_UNPACK
#include <bpkg/types>
+#include <bpkg/forward> // transaction, selected_package
#include <bpkg/pkg-unpack-options>
namespace bpkg
{
void
pkg_unpack (const pkg_unpack_options&, cli::scanner& args);
+
+ // Unpack the package as a source directory and commit the transaction.
+ //
+ shared_ptr<selected_package>
+ pkg_unpack (const dir_path& configuration,
+ transaction&,
+ const dir_path&,
+ bool replace,
+ bool purge);
+
+ // Unpack the fetched package and commit the transaction.
+ //
+ shared_ptr<selected_package>
+ pkg_unpack (const common_options&,
+ const dir_path& configuration,
+ transaction&,
+ const string& name);
}
#endif // BPKG_PKG_UNPACK
diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx
index 7100809..d6613b5 100644
--- a/bpkg/pkg-unpack.cxx
+++ b/bpkg/pkg-unpack.cxx
@@ -23,14 +23,16 @@ using namespace butl;
namespace bpkg
{
- static shared_ptr<selected_package>
- pkg_unpack (database& db,
- const dir_path& c,
+ shared_ptr<selected_package>
+ pkg_unpack (const dir_path& c,
+ transaction& t,
const dir_path& d,
bool replace,
bool purge)
{
- tracer trace ("pkg_unpack(dir)");
+ tracer trace ("pkg_unpack");
+
+ database& db (t.database ());
tracer_guard tg (db, trace);
if (!exists (d))
@@ -52,8 +54,6 @@ namespace bpkg
if (ad.sub (ac))
ad = ad.leaf (ac);
- transaction t (db.begin ());
-
// See if this package already exists in this configuration.
//
const string& n (m.name);
@@ -112,16 +112,17 @@ namespace bpkg
return p;
}
- static shared_ptr<selected_package>
+ shared_ptr<selected_package>
pkg_unpack (const common_options& co,
- database& db,
const dir_path& c,
+ transaction& t,
const string& name)
{
- tracer trace ("pkg_unpack(pkg)");
+ tracer trace ("pkg_unpack");
+
+ database& db (t.database ());
tracer_guard tg (db, trace);
- transaction t (db.begin ());
shared_ptr<selected_package> p (db.find<selected_package> (name));
if (p == nullptr)
@@ -224,6 +225,7 @@ namespace bpkg
level4 ([&]{trace << "configuration: " << c;});
database db (open (c, trace));
+ transaction t (db.begin ());
shared_ptr<selected_package> p;
@@ -236,7 +238,7 @@ namespace bpkg
info << "run 'bpkg help pkg-unpack' for more information";
p = pkg_unpack (
- db, c, dir_path (args.next ()), o.replace (), o.purge ());
+ c, t, dir_path (args.next ()), o.replace (), o.purge ());
}
else
{
@@ -246,7 +248,7 @@ namespace bpkg
fail << "package name argument expected" <<
info << "run 'bpkg help pkg-unpack' for more information";
- p = pkg_unpack (o, db, c, args.next ());
+ p = pkg_unpack (o, c, t, args.next ());
}
if (verb)
diff --git a/bpkg/pkg-update b/bpkg/pkg-update
index 4c89e66..b34e44a 100644
--- a/bpkg/pkg-update
+++ b/bpkg/pkg-update
@@ -6,6 +6,7 @@
#define BPKG_PKG_UPDATE
#include <bpkg/types>
+#include <bpkg/forward> // selected_package
#include <bpkg/pkg-command>
#include <bpkg/pkg-update-options>
@@ -16,6 +17,13 @@ namespace bpkg
{
pkg_command ("update", o, args);
}
+
+ inline void
+ pkg_update (const dir_path& configuration,
+ const shared_ptr<selected_package>& p)
+ {
+ pkg_command ("update", configuration, p);
+ }
}
#endif // BPKG_PKG_UPDATE
diff --git a/bpkg/test.sh b/bpkg/test.sh
index 4a99347..6e4d5de 100755
--- a/bpkg/test.sh
+++ b/bpkg/test.sh
@@ -233,7 +233,6 @@ test pkg-fetch libhello/1.0.0
test pkg-unpack libhello
test pkg-purge libhello
-
## @@
##
##