aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-10-22 11:07:03 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-10-22 11:07:03 +0200
commite6f10cabb7fbdba6fd11bcd109dbe765285c762c (patch)
tree350e0bf1230e930d2c9512eab396a80ffc98b610
parent56af938cd423c1b6730d753ba1ce7b70cd660c29 (diff)
Implement dependents check in drop command
Also, add support for commands to return program status.
-rw-r--r--bpkg/bpkg.cxx10
-rw-r--r--bpkg/build2
-rw-r--r--bpkg/build.cxx8
-rw-r--r--bpkg/cfg-create2
-rw-r--r--bpkg/cfg-create.cxx4
-rw-r--r--bpkg/drop2
-rw-r--r--bpkg/drop-options.cli11
-rw-r--r--bpkg/drop.cxx99
-rw-r--r--bpkg/help2
-rw-r--r--bpkg/help.cxx4
-rw-r--r--bpkg/pkg-clean4
-rw-r--r--bpkg/pkg-command2
-rw-r--r--bpkg/pkg-command.cxx4
-rw-r--r--bpkg/pkg-configure2
-rw-r--r--bpkg/pkg-configure.cxx4
-rw-r--r--bpkg/pkg-disfigure2
-rw-r--r--bpkg/pkg-disfigure.cxx4
-rw-r--r--bpkg/pkg-fetch2
-rw-r--r--bpkg/pkg-fetch.cxx4
-rw-r--r--bpkg/pkg-purge2
-rw-r--r--bpkg/pkg-purge.cxx4
-rw-r--r--bpkg/pkg-status2
-rw-r--r--bpkg/pkg-status.cxx3
-rw-r--r--bpkg/pkg-unpack2
-rw-r--r--bpkg/pkg-unpack.cxx4
-rw-r--r--bpkg/pkg-update4
-rw-r--r--bpkg/pkg-verify2
-rw-r--r--bpkg/pkg-verify.cxx17
-rw-r--r--bpkg/rep-add2
-rw-r--r--bpkg/rep-add.cxx4
-rw-r--r--bpkg/rep-create2
-rw-r--r--bpkg/rep-create.cxx7
-rw-r--r--bpkg/rep-fetch2
-rw-r--r--bpkg/rep-fetch.cxx4
-rw-r--r--bpkg/rep-info2
-rw-r--r--bpkg/rep-info.cxx4
-rwxr-xr-xtests/test.sh23
37 files changed, 215 insertions, 47 deletions
diff --git a/bpkg/bpkg.cxx b/bpkg/bpkg.cxx
index 61f7425..6246d6f 100644
--- a/bpkg/bpkg.cxx
+++ b/bpkg/bpkg.cxx
@@ -145,6 +145,7 @@ try
// Handle commands.
//
+ int r (1);
for (;;)
{
// help
@@ -152,7 +153,7 @@ try
if (cmd.help ())
{
assert (h);
- help (ho, "help", help_options::print_usage);
+ r = help (ho, "help", help_options::print_usage);
break;
}
@@ -163,7 +164,7 @@ try
// if (h)
// help (ho, "pkg-verify", pkg_verify_options::print_usage);
// else
- // pkg_verify (parse<pkg_verify_options> (co, args), args);
+ // r = pkg_verify (parse<pkg_verify_options> (co, args), args);
//
// return 0;
// }
@@ -174,7 +175,7 @@ try
if (h) \
help (ho, SP#CMD, NP##CMD##_options::print_usage); \
else \
- NP##CMD (parse<NP##CMD##_options> (co, args), args); \
+ r = NP##CMD (parse<NP##CMD##_options> (co, args), args); \
\
break; \
}
@@ -219,6 +220,9 @@ try
fail << "unhandled command";
}
+ if (r != 0)
+ return r;
+
// Warn if args contain some leftover junk. We already successfully
// performed the command so failing would probably be misleading.
//
diff --git a/bpkg/build b/bpkg/build
index cc89599..a5c047d 100644
--- a/bpkg/build
+++ b/bpkg/build
@@ -10,7 +10,7 @@
namespace bpkg
{
- void
+ int
build (const build_options&, cli::scanner& args);
}
diff --git a/bpkg/build.cxx b/bpkg/build.cxx
index ec9de3b..1aeb35d 100644
--- a/bpkg/build.cxx
+++ b/bpkg/build.cxx
@@ -731,7 +731,7 @@ namespace bpkg
map_type map_;
};
- void
+ int
build (const build_options& o, cli::scanner& args)
{
tracer trace ("build");
@@ -1029,12 +1029,12 @@ namespace bpkg
}
if (o.print_only ())
- return;
+ return 0;
// Ask the user if we should continue.
//
if (!(o.yes () || yn_prompt ("continue? [Y/n]", 'y')))
- return;
+ return 1;
// Ok, we have the green light. The overall action plan is as follows.
//
@@ -1230,5 +1230,7 @@ namespace bpkg
text << "updated " << sp->name << " " << sp->version;
}
}
+
+ return 0;
}
}
diff --git a/bpkg/cfg-create b/bpkg/cfg-create
index ffd3ba5..b6dcc21 100644
--- a/bpkg/cfg-create
+++ b/bpkg/cfg-create
@@ -10,7 +10,7 @@
namespace bpkg
{
- void
+ int
cfg_create (const cfg_create_options&, cli::scanner& args);
}
diff --git a/bpkg/cfg-create.cxx b/bpkg/cfg-create.cxx
index bbb624c..c98dd28 100644
--- a/bpkg/cfg-create.cxx
+++ b/bpkg/cfg-create.cxx
@@ -18,7 +18,7 @@ using namespace butl;
namespace bpkg
{
- void
+ int
cfg_create (const cfg_create_options& o, cli::scanner& args)
{
tracer trace ("cfg_create");
@@ -130,5 +130,7 @@ namespace bpkg
c.complete ().normalize ();
text << "created new configuration in " << c;
}
+
+ return 0;
}
}
diff --git a/bpkg/drop b/bpkg/drop
index 1687c82..0054045 100644
--- a/bpkg/drop
+++ b/bpkg/drop
@@ -10,7 +10,7 @@
namespace bpkg
{
- void
+ int
drop (const drop_options&, cli::scanner& args);
}
diff --git a/bpkg/drop-options.cli b/bpkg/drop-options.cli
index 301bc9a..d1a3769 100644
--- a/bpkg/drop-options.cli
+++ b/bpkg/drop-options.cli
@@ -31,10 +31,17 @@ namespace bpkg
bool --yes|-y
{
"Assume the answer to all prompts is \cb{yes}. Note that this option
- does not apply to the dropping of dependents confirmation."
+ does not apply to the dropping of dependents; use \cb{--drop-dependent}
+ for that."
};
- bool --disfigure-only|-d
+ bool --drop-dependent
+ {
+ "Don't warn about or ask for confirmation of dropping dependent
+ packages."
+ };
+
+ bool --disfigure-only
{
"Disfigure all the packages but don't purge."
};
diff --git a/bpkg/drop.cxx b/bpkg/drop.cxx
index ac3919e..e2fd455 100644
--- a/bpkg/drop.cxx
+++ b/bpkg/drop.cxx
@@ -4,6 +4,7 @@
#include <bpkg/drop>
+#include <map>
#include <iostream> // cout
#include <butl/utility> // reverse_iterate()
@@ -27,7 +28,41 @@ using namespace butl;
namespace bpkg
{
- void
+ using package_map = map<string, shared_ptr<selected_package>>;
+
+ static void
+ collect_dependent (database& db,
+ package_map& m,
+ const shared_ptr<selected_package>& p,
+ bool w)
+ {
+ using query = query<package_dependent>;
+
+ bool found (false);
+
+ for (auto& pd: db.query<package_dependent> (query::name == p->name))
+ {
+ string& dn (pd.name);
+
+ if (m.find (dn) == m.end ())
+ {
+ shared_ptr<selected_package> dp (db.load<selected_package> (dn));
+ m.emplace (move (dn), dp);
+
+ collect_dependent (db, m, dp, w);
+
+ if (w)
+ warn << "dependent package " << dp->name << " to be dropped as well";
+
+ found = true;
+ }
+ }
+
+ if (w && found)
+ info << "because dropping " << p->name;
+ }
+
+ int
drop (const drop_options& o, cli::scanner& args)
{
tracer trace ("drop");
@@ -47,6 +82,68 @@ namespace bpkg
// any of these objects, they will modify the cached instance, which
// means our list will always "see" their updated state.
//
+ // @@ Revise.
+ //
session s;
+
+ // Assemble the list of packages we will need to drop. Comparing pointers
+ // is valid because of the session above.
+ //
+ package_map pkgs;
+ vector<string> names;
+ {
+ transaction t (db.begin ());
+
+ // The first step is to load all the packages specified by the user.
+ //
+ while (args.more ())
+ {
+ string n (args.next ());
+ level4 ([&]{trace << "package " << n;});
+
+ 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::broken)
+ fail << "unable to drop broken package " << n <<
+ info << "use 'pkg-purge --force' to remove";
+
+ if (pkgs.emplace (n, move (p)).second)
+ names.push_back (move (n));
+ }
+
+ // The next step is to see if there are any dependents that are not
+ // already on the list. We will have to drop those as well.
+ //
+ for (const string& n: names)
+ {
+ const shared_ptr<selected_package>& p (pkgs[n]);
+
+ // Unconfigured package cannot have any dependents.
+ //
+ if (p->state != package_state::configured)
+ continue;
+
+ collect_dependent (db, pkgs, p, !o.drop_dependent ());
+ }
+
+ // If we've found dependents, ask the user to confirm.
+ //
+ if (!o.drop_dependent () && names.size () != pkgs.size ())
+ {
+ if (o.yes ())
+ fail << "refusing to drop dependent packages with just --yes" <<
+ info << "specify --drop-dependent to confirm";
+
+ if (!yn_prompt ("drop dependent packages? [y/N]", 'n'))
+ return 1;
+ }
+
+ t.commit ();
+ }
+
+ return 0;
}
}
diff --git a/bpkg/help b/bpkg/help
index 9c81e7e..8bd5596 100644
--- a/bpkg/help
+++ b/bpkg/help
@@ -12,7 +12,7 @@
namespace bpkg
{
- void
+ int
help (const help_options&,
const string& topic,
void (*usage) (std::ostream&));
diff --git a/bpkg/help.cxx b/bpkg/help.cxx
index 66b68aa..f03ad21 100644
--- a/bpkg/help.cxx
+++ b/bpkg/help.cxx
@@ -51,7 +51,7 @@ namespace bpkg
o << ""<< endl;
}
- void
+ int
help (const help_options&, const string& t, void (*usage) (std::ostream&))
{
ostream& o (cout);
@@ -77,5 +77,7 @@ namespace bpkg
else
fail << "unknown bpkg command/help topic '" << t << "'" <<
info << "run 'bpkg help' for more information";
+
+ return 0;
}
}
diff --git a/bpkg/pkg-clean b/bpkg/pkg-clean
index baed20a..1195cfe 100644
--- a/bpkg/pkg-clean
+++ b/bpkg/pkg-clean
@@ -11,10 +11,10 @@
namespace bpkg
{
- inline void
+ inline int
pkg_clean (const pkg_clean_options& o, cli::scanner& args)
{
- pkg_command ("clean", o, args);
+ return pkg_command ("clean", o, args);
}
}
diff --git a/bpkg/pkg-command b/bpkg/pkg-command
index 360a550..724caa8 100644
--- a/bpkg/pkg-command
+++ b/bpkg/pkg-command
@@ -13,7 +13,7 @@ namespace bpkg
{
// Common pkg-{update,clean,test,install,...} implementation.
//
- void
+ int
pkg_command (const string& cmd, // Without the 'pkg-' prefix.
const configuration_options&,
cli::scanner& args);
diff --git a/bpkg/pkg-command.cxx b/bpkg/pkg-command.cxx
index 67ea07a..253ee66 100644
--- a/bpkg/pkg-command.cxx
+++ b/bpkg/pkg-command.cxx
@@ -39,7 +39,7 @@ namespace bpkg
run_b (bspec);
}
- void
+ int
pkg_command (const string& cmd,
const configuration_options& o,
cli::scanner& args)
@@ -75,5 +75,7 @@ namespace bpkg
if (verb)
text << cmd << (cmd.back () != 'e' ? "ed " : "d ")
<< p->name << " " << p->version;
+
+ return 0;
}
}
diff --git a/bpkg/pkg-configure b/bpkg/pkg-configure
index b042e60..df2fc40 100644
--- a/bpkg/pkg-configure
+++ b/bpkg/pkg-configure
@@ -11,7 +11,7 @@
namespace bpkg
{
- void
+ int
pkg_configure (const pkg_configure_options&, cli::scanner& args);
// Configure the package, update its state, and commit the transaction.
diff --git a/bpkg/pkg-configure.cxx b/bpkg/pkg-configure.cxx
index 9e256ce..f7e1901 100644
--- a/bpkg/pkg-configure.cxx
+++ b/bpkg/pkg-configure.cxx
@@ -144,7 +144,7 @@ namespace bpkg
t.commit ();
}
- void
+ int
pkg_configure (const pkg_configure_options& o, cli::scanner& args)
{
tracer trace ("pkg_configure");
@@ -192,5 +192,7 @@ namespace bpkg
if (verb)
text << "configured " << p->name << " " << p->version;
+
+ return 0;
}
}
diff --git a/bpkg/pkg-disfigure b/bpkg/pkg-disfigure
index ef78d05..2833522 100644
--- a/bpkg/pkg-disfigure
+++ b/bpkg/pkg-disfigure
@@ -11,7 +11,7 @@
namespace bpkg
{
- void
+ int
pkg_disfigure (const pkg_disfigure_options&, cli::scanner& args);
// Disfigure the package, update its state, and commit the
diff --git a/bpkg/pkg-disfigure.cxx b/bpkg/pkg-disfigure.cxx
index d9e5552..465213b 100644
--- a/bpkg/pkg-disfigure.cxx
+++ b/bpkg/pkg-disfigure.cxx
@@ -127,7 +127,7 @@ namespace bpkg
t.commit ();
}
- void
+ int
pkg_disfigure (const pkg_disfigure_options& o, cli::scanner& args)
{
tracer trace ("pkg_disfigure");
@@ -159,5 +159,7 @@ namespace bpkg
if (verb)
text << "disfigured " << p->name << " " << p->version;
+
+ return 0;
}
}
diff --git a/bpkg/pkg-fetch b/bpkg/pkg-fetch
index 7cfd214..d321889 100644
--- a/bpkg/pkg-fetch
+++ b/bpkg/pkg-fetch
@@ -13,7 +13,7 @@
namespace bpkg
{
- void
+ int
pkg_fetch (const pkg_fetch_options&, cli::scanner& args);
// Fetch the package as an archive file and commit the transaction.
diff --git a/bpkg/pkg-fetch.cxx b/bpkg/pkg-fetch.cxx
index 9a2e84c..492c4e7 100644
--- a/bpkg/pkg-fetch.cxx
+++ b/bpkg/pkg-fetch.cxx
@@ -226,7 +226,7 @@ namespace bpkg
return p;
}
- void
+ int
pkg_fetch (const pkg_fetch_options& o, cli::scanner& args)
{
tracer trace ("pkg_fetch");
@@ -269,5 +269,7 @@ namespace bpkg
if (verb)
text << "fetched " << p->name << " " << p->version;
+
+ return 0;
}
}
diff --git a/bpkg/pkg-purge b/bpkg/pkg-purge
index 0c88e19..399606d 100644
--- a/bpkg/pkg-purge
+++ b/bpkg/pkg-purge
@@ -11,7 +11,7 @@
namespace bpkg
{
- void
+ int
pkg_purge (const pkg_purge_options&, cli::scanner& args);
// Remove package's filesystem objects (the source directory and, if
diff --git a/bpkg/pkg-purge.cxx b/bpkg/pkg-purge.cxx
index 47ff05f..b90136a 100644
--- a/bpkg/pkg-purge.cxx
+++ b/bpkg/pkg-purge.cxx
@@ -66,7 +66,7 @@ namespace bpkg
}
}
- void
+ int
pkg_purge (const pkg_purge_options& o, cli::scanner& args)
{
tracer trace ("pkg_purge");
@@ -182,5 +182,7 @@ namespace bpkg
if (verb)
text << (o.keep () ? "keeping archive " : "purged ")
<< p->name << " " << p->version;
+
+ return 0;
}
}
diff --git a/bpkg/pkg-status b/bpkg/pkg-status
index 98bd014..175ea87 100644
--- a/bpkg/pkg-status
+++ b/bpkg/pkg-status
@@ -10,7 +10,7 @@
namespace bpkg
{
- void
+ int
pkg_status (const pkg_status_options&, cli::scanner& args);
}
diff --git a/bpkg/pkg-status.cxx b/bpkg/pkg-status.cxx
index 2f0bf7f..c31e834 100644
--- a/bpkg/pkg-status.cxx
+++ b/bpkg/pkg-status.cxx
@@ -20,7 +20,7 @@ using namespace butl;
namespace bpkg
{
- void
+ int
pkg_status (const pkg_status_options& o, cli::scanner& args)
{
tracer trace ("pkg_status");
@@ -129,5 +129,6 @@ namespace bpkg
cout << "unknown";
cout << endl;
+ return 0;
}
}
diff --git a/bpkg/pkg-unpack b/bpkg/pkg-unpack
index a569efe..1e5339d 100644
--- a/bpkg/pkg-unpack
+++ b/bpkg/pkg-unpack
@@ -11,7 +11,7 @@
namespace bpkg
{
- void
+ int
pkg_unpack (const pkg_unpack_options&, cli::scanner& args);
// Unpack the package as a source directory and commit the transaction.
diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx
index c224350..5af8a10 100644
--- a/bpkg/pkg-unpack.cxx
+++ b/bpkg/pkg-unpack.cxx
@@ -215,7 +215,7 @@ namespace bpkg
return p;
}
- void
+ int
pkg_unpack (const pkg_unpack_options& o, cli::scanner& args)
{
tracer trace ("pkg_unpack");
@@ -255,5 +255,7 @@ namespace bpkg
if (verb)
text << "unpacked " << p->name << " " << p->version;
+
+ return 0;
}
}
diff --git a/bpkg/pkg-update b/bpkg/pkg-update
index b34e44a..a266da3 100644
--- a/bpkg/pkg-update
+++ b/bpkg/pkg-update
@@ -12,10 +12,10 @@
namespace bpkg
{
- inline void
+ inline int
pkg_update (const pkg_update_options& o, cli::scanner& args)
{
- pkg_command ("update", o, args);
+ return pkg_command ("update", o, args);
}
inline void
diff --git a/bpkg/pkg-verify b/bpkg/pkg-verify
index e0675c6..8a62b66 100644
--- a/bpkg/pkg-verify
+++ b/bpkg/pkg-verify
@@ -12,7 +12,7 @@
namespace bpkg
{
- void
+ int
pkg_verify (const pkg_verify_options&, cli::scanner& args);
// Verify archive is a valid package and return its manifest. Throw
diff --git a/bpkg/pkg-verify.cxx b/bpkg/pkg-verify.cxx
index 969eb22..5e16410 100644
--- a/bpkg/pkg-verify.cxx
+++ b/bpkg/pkg-verify.cxx
@@ -208,7 +208,7 @@ namespace bpkg
}
}
- void
+ int
pkg_verify (const pkg_verify_options& o, cli::scanner& args)
{
tracer trace ("pkg_verify");
@@ -227,9 +227,18 @@ namespace bpkg
// If we were asked to run silent, don't yap about the reason
// why the package is invalid. Just return the error status.
//
- package_manifest m (pkg_verify (o, a, !o.silent ()));
+ try
+ {
+ package_manifest m (pkg_verify (o, a, !o.silent ()));
+
+ if (verb && !o.silent ())
+ text << "valid package " << m.name << " " << m.version;
- if (verb && !o.silent ())
- text << "valid package " << m.name << " " << m.version;
+ return 0;
+ }
+ catch (const failed&)
+ {
+ return 1;
+ }
}
}
diff --git a/bpkg/rep-add b/bpkg/rep-add
index 3aff082..10d85f4 100644
--- a/bpkg/rep-add
+++ b/bpkg/rep-add
@@ -10,7 +10,7 @@
namespace bpkg
{
- void
+ int
rep_add (const rep_add_options&, cli::scanner& args);
}
diff --git a/bpkg/rep-add.cxx b/bpkg/rep-add.cxx
index bed6b86..4348206 100644
--- a/bpkg/rep-add.cxx
+++ b/bpkg/rep-add.cxx
@@ -19,7 +19,7 @@ using namespace butl;
namespace bpkg
{
- void
+ int
rep_add (const rep_add_options& o, cli::scanner& args)
{
tracer trace ("rep_add");
@@ -64,5 +64,7 @@ namespace bpkg
if (verb)
text << "added " << rn;
+
+ return 0;
}
}
diff --git a/bpkg/rep-create b/bpkg/rep-create
index 7ce693e..322c76c 100644
--- a/bpkg/rep-create
+++ b/bpkg/rep-create
@@ -10,7 +10,7 @@
namespace bpkg
{
- void
+ int
rep_create (const rep_create_options&, cli::scanner& args);
}
diff --git a/bpkg/rep-create.cxx b/bpkg/rep-create.cxx
index 291374e..1f0e420 100644
--- a/bpkg/rep-create.cxx
+++ b/bpkg/rep-create.cxx
@@ -131,7 +131,7 @@ namespace bpkg
throw failed ();
}
- void
+ int
rep_create (const rep_create_options& o, cli::scanner& args)
try
{
@@ -195,9 +195,12 @@ namespace bpkg
d.normalize ();
text << pm.size () << " package(s) in " << d;
}
+
+ return 0;
}
catch (const invalid_path& e)
{
- fail << "invalid path: '" << e.path () << "'";
+ error << "invalid path: '" << e.path () << "'";
+ throw failed ();
}
}
diff --git a/bpkg/rep-fetch b/bpkg/rep-fetch
index 9977571..9175755 100644
--- a/bpkg/rep-fetch
+++ b/bpkg/rep-fetch
@@ -10,7 +10,7 @@
namespace bpkg
{
- void
+ int
rep_fetch (const rep_fetch_options&, cli::scanner& args);
}
diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx
index 7443f56..f96607f 100644
--- a/bpkg/rep-fetch.cxx
+++ b/bpkg/rep-fetch.cxx
@@ -175,7 +175,7 @@ namespace bpkg
db.update (r);
}
- void
+ int
rep_fetch (const rep_fetch_options& o, cli::scanner&)
{
tracer trace ("rep_fetch");
@@ -239,5 +239,7 @@ namespace bpkg
if (verb)
text << pcount << " package(s) in " << rcount << " repository(s)";
+
+ return 0;
}
}
diff --git a/bpkg/rep-info b/bpkg/rep-info
index 8437a53..ef01369 100644
--- a/bpkg/rep-info
+++ b/bpkg/rep-info
@@ -10,7 +10,7 @@
namespace bpkg
{
- void
+ int
rep_info (const rep_info_options&, cli::scanner& args);
}
diff --git a/bpkg/rep-info.cxx b/bpkg/rep-info.cxx
index 8bb3c7d..041d804 100644
--- a/bpkg/rep-info.cxx
+++ b/bpkg/rep-info.cxx
@@ -21,7 +21,7 @@ using namespace butl;
namespace bpkg
{
- void
+ int
rep_info (const rep_info_options& o, cli::scanner& args)
{
tracer trace ("rep_info");
@@ -108,5 +108,7 @@ namespace bpkg
{
fail << "unable to write to STDOUT";
}
+
+ return 0;
}
}
diff --git a/tests/test.sh b/tests/test.sh
index c6c8a79..932b0d6 100755
--- a/tests/test.sh
+++ b/tests/test.sh
@@ -153,6 +153,8 @@ function gone ()
fi
}
+#if false; then
+
##
## rep-create
##
@@ -1129,3 +1131,24 @@ test rep-add $rep/satisfy/t4c
test rep-fetch
test build -y libbaz
stat libfoo "configured 1.1.0"
+
+##
+## drop
+##
+test cfg-create --wipe
+
+fail drop -p # package name expected
+fail drop -p libfoo # unknown package
+fail drop -p libfoo/1.0.0 # unknown package
+
+# dependents
+#
+test cfg-create --wipe
+test rep-add $rep/satisfy/t4c
+test rep-fetch
+test build -y libbaz
+fail drop -y libfoo
+fail drop -y libfoo libbar
+fail drop -y libfoo libbaz
+test drop -y libfoo libbaz libbar
+test drop -y --drop-dependent libfoo