aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-09-17 14:05:22 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-09-17 14:05:22 +0200
commit7221a63204a0b2a89e1c72fcbf9f2a7de0a575a3 (patch)
treecfd02eebc09b6700441d252513f692d1a67ed34f
parent299c4e373d2c2642a8e4c3537eb0436c5a6b9c09 (diff)
Implement pkg-{configure, disfigure} commands
-rw-r--r--bpkg/bpkg-options.cli14
-rw-r--r--bpkg/bpkg.cxx28
-rw-r--r--bpkg/buildfile38
-rw-r--r--bpkg/forward20
-rw-r--r--bpkg/package15
-rw-r--r--bpkg/package.xml7
-rw-r--r--bpkg/pkg-configure17
-rw-r--r--bpkg/pkg-configure-options.cli36
-rw-r--r--bpkg/pkg-configure.cxx122
-rw-r--r--bpkg/pkg-disfigure26
-rw-r--r--bpkg/pkg-disfigure-options.cli32
-rw-r--r--bpkg/pkg-disfigure.cxx124
-rw-r--r--bpkg/pkg-fetch.cxx7
-rw-r--r--bpkg/pkg-purge.cxx41
-rw-r--r--bpkg/pkg-unpack.cxx22
-rw-r--r--bpkg/rep-create.cxx3
-rwxr-xr-xbpkg/test.sh103
17 files changed, 594 insertions, 61 deletions
diff --git a/bpkg/bpkg-options.cli b/bpkg/bpkg-options.cli
index 710b809..e694c3b 100644
--- a/bpkg/bpkg-options.cli
+++ b/bpkg/bpkg-options.cli
@@ -56,6 +56,20 @@ namespace bpkg
""
};
+ bool pkg-configure
+ {
+ "<pkg>",
+ "Configure package.",
+ ""
+ };
+
+ bool pkg-disfigure
+ {
+ "<pkg>",
+ "Disfigure package.",
+ ""
+ };
+
bool cfg-create
{
"[<conf>]",
diff --git a/bpkg/bpkg.cxx b/bpkg/bpkg.cxx
index 994f115..61bd330 100644
--- a/bpkg/bpkg.cxx
+++ b/bpkg/bpkg.cxx
@@ -14,11 +14,15 @@
// Commands.
//
#include <bpkg/help>
+
#include <bpkg/pkg-verify>
#include <bpkg/pkg-status>
#include <bpkg/pkg-fetch>
#include <bpkg/pkg-unpack>
#include <bpkg/pkg-purge>
+#include <bpkg/pkg-configure>
+#include <bpkg/pkg-disfigure>
+
#include <bpkg/cfg-create>
#include <bpkg/rep-create>
@@ -200,6 +204,30 @@ try
return 0;
}
+ // pkg-configure
+ //
+ if (cmd.pkg_configure ())
+ {
+ if (h)
+ help (ho, "pkg-configure", pkg_configure_options::print_usage);
+ else
+ pkg_configure (parse<pkg_configure_options> (co, args), args);
+
+ return 0;
+ }
+
+ // pkg-disfigure
+ //
+ if (cmd.pkg_disfigure ())
+ {
+ if (h)
+ help (ho, "pkg-disfigure", pkg_disfigure_options::print_usage);
+ else
+ pkg_disfigure (parse<pkg_disfigure_options> (co, args), args);
+
+ return 0;
+ }
+
// cfg-create
//
if (cmd.cfg_create ())
diff --git a/bpkg/buildfile b/bpkg/buildfile
index 0d9742d..b24fedb 100644
--- a/bpkg/buildfile
+++ b/bpkg/buildfile
@@ -10,16 +10,18 @@ import libs += libodb%lib{odb}
import libs += libodb-sqlite%lib{odb-sqlite}
exe{bpkg}: cxx{package package-odb database diagnostics utility} \
- cli.cxx{common-options} cxx{types-parsers} \
- cxx{bpkg} cli.cxx{bpkg-options} \
- cxx{help} cli.cxx{help-options} \
- cxx{pkg-verify} cli.cxx{pkg-verify-options} \
- cxx{pkg-status} cli.cxx{pkg-status-options} \
- cxx{pkg-fetch} cli.cxx{pkg-fetch-options} \
- cxx{pkg-unpack} cli.cxx{pkg-unpack-options} \
- cxx{pkg-purge} cli.cxx{pkg-purge-options} \
- cxx{cfg-create} cli.cxx{cfg-create-options} \
- cxx{rep-create} cli.cxx{rep-create-options} \
+ cli.cxx{common-options} cxx{types-parsers} \
+ cxx{bpkg} cli.cxx{bpkg-options} \
+ cxx{help} cli.cxx{help-options} \
+ cxx{pkg-verify} cli.cxx{pkg-verify-options} \
+ cxx{pkg-status} cli.cxx{pkg-status-options} \
+ cxx{pkg-fetch} cli.cxx{pkg-fetch-options} \
+ cxx{pkg-unpack} cli.cxx{pkg-unpack-options} \
+ cxx{pkg-purge} cli.cxx{pkg-purge-options} \
+ cxx{pkg-configure} cli.cxx{pkg-configure-options} \
+ cxx{pkg-disfigure} cli.cxx{pkg-disfigure-options} \
+ cxx{cfg-create} cli.cxx{cfg-create-options} \
+ cxx{rep-create} cli.cxx{rep-create-options} \
$libs
cli.options += -I $src_root --include-with-brackets --include-prefix bpkg \
@@ -38,10 +40,12 @@ cli.cxx{bpkg-options}: cli.options += --option-length 22 --short-usage
cli.cxx{help-options}: cli{help-options}
-cli.cxx{pkg-verify-options}: cli{pkg-verify-options}
-cli.cxx{pkg-status-options}: cli{pkg-status-options}
-cli.cxx{pkg-fetch-options}: cli{pkg-fetch-options}
-cli.cxx{pkg-unpack-options}: cli{pkg-unpack-options}
-cli.cxx{pkg-purge-options}: cli{pkg-purge-options}
-cli.cxx{cfg-create-options}: cli{cfg-create-options}
-cli.cxx{rep-create-options}: cli{rep-create-options}
+cli.cxx{pkg-verify-options}: cli{pkg-verify-options}
+cli.cxx{pkg-status-options}: cli{pkg-status-options}
+cli.cxx{pkg-fetch-options}: cli{pkg-fetch-options}
+cli.cxx{pkg-unpack-options}: cli{pkg-unpack-options}
+cli.cxx{pkg-purge-options}: cli{pkg-purge-options}
+cli.cxx{pkg-configure-options}: cli{pkg-configure-options}
+cli.cxx{pkg-disfigure-options}: cli{pkg-disfigure-options}
+cli.cxx{cfg-create-options}: cli{cfg-create-options}
+cli.cxx{rep-create-options}: cli{rep-create-options}
diff --git a/bpkg/forward b/bpkg/forward
new file mode 100644
index 0000000..cddc89f
--- /dev/null
+++ b/bpkg/forward
@@ -0,0 +1,20 @@
+// file : bpkg/forward -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BPKG_FORWARD
+#define BPKG_FORWARD
+
+#include <odb/sqlite/forward.hxx>
+
+namespace bpkg
+{
+ using odb::sqlite::database;
+ using odb::sqlite::transaction;
+
+ // <bpkg/package>
+ //
+ class package;
+}
+
+#endif // BPKG_FORWARD
diff --git a/bpkg/package b/bpkg/package
index 48b7ec8..f2c9b9a 100644
--- a/bpkg/package
+++ b/bpkg/package
@@ -108,7 +108,7 @@ namespace bpkg
// be false.
//
optional<path> archive;
- bool archive_purge;
+ bool purge_archive;
// Path to the source directory of this package, if any. If not
// absolute, then it is relative to the configuration directory.
@@ -116,8 +116,17 @@ namespace bpkg
// removed when the packaged is purged. If the source directory
// is not present, it should be false.
//
- optional<dir_path> source;
- bool source_purge;
+ optional<dir_path> src_root;
+ bool purge_src;
+
+ // Path to the output directory of this package, if any. It is
+ // always relative to the configuration directory and currently
+ // is always <name>-<version>. It is only set once the package
+ // is configured and its main purse is to keep track of what
+ // needs to be cleaned by the user before a broken package can
+ // be purged. Note that it could be the same as out_root.
+ //
+ optional<dir_path> out_root;
// Database mapping.
//
diff --git a/bpkg/package.xml b/bpkg/package.xml
index 5140717..4bea324 100644
--- a/bpkg/package.xml
+++ b/bpkg/package.xml
@@ -8,9 +8,10 @@
<column name="version_canonical_upstream" type="TEXT" null="true"/>
<column name="state" type="TEXT" null="true"/>
<column name="archive" type="TEXT" null="true"/>
- <column name="archive_purge" type="INTEGER" null="true"/>
- <column name="source" type="TEXT" null="true"/>
- <column name="source_purge" type="INTEGER" null="true"/>
+ <column name="purge_archive" type="INTEGER" null="true"/>
+ <column name="src_root" type="TEXT" null="true"/>
+ <column name="purge_src" type="INTEGER" null="true"/>
+ <column name="out_root" type="TEXT" null="true"/>
<primary-key>
<column name="name"/>
</primary-key>
diff --git a/bpkg/pkg-configure b/bpkg/pkg-configure
new file mode 100644
index 0000000..e314e52
--- /dev/null
+++ b/bpkg/pkg-configure
@@ -0,0 +1,17 @@
+// file : bpkg/pkg-configure -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BPKG_PKG_CONFIGURE
+#define BPKG_PKG_CONFIGURE
+
+#include <bpkg/types>
+#include <bpkg/pkg-configure-options>
+
+namespace bpkg
+{
+ void
+ pkg_configure (const pkg_configure_options&, cli::scanner& args);
+}
+
+#endif // BPKG_PKG_CONFIGURE
diff --git a/bpkg/pkg-configure-options.cli b/bpkg/pkg-configure-options.cli
new file mode 100644
index 0000000..d1850c6
--- /dev/null
+++ b/bpkg/pkg-configure-options.cli
@@ -0,0 +1,36 @@
+// file : bpkg/pkg-configure-options.cli
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+include <bpkg/common-options.cli>;
+
+/*
+"\section=1"
+"\name=bpkg-pkg-configure"
+
+"\h{SYNOPSIS}
+
+bpkg pkg-configure <pkg> [<conf-vars>]"
+
+"\h{DESCRIPTION}
+
+The \cb{pkg-configure} command configures the output directory for
+the previously unpacked (\cb{pkg-unpack}) package. The package
+inherits the common \cb{build2} configuration values that were
+specified when creating the \cb{bpkg} configuration (\cb{cfg-create}).
+Additional, package-specific configuration variables can be specified
+after the package name."
+*/
+
+namespace bpkg
+{
+ class pkg_configure_options: common_options
+ {
+ dir_path --directory|-d (".")
+ {
+ "<dir>",
+ "Assume configuration is in <dir> rather than in the current working
+ directory."
+ };
+ };
+}
diff --git a/bpkg/pkg-configure.cxx b/bpkg/pkg-configure.cxx
new file mode 100644
index 0000000..e680b61
--- /dev/null
+++ b/bpkg/pkg-configure.cxx
@@ -0,0 +1,122 @@
+// file : bpkg/pkg-configure.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <bpkg/pkg-configure>
+
+#include <bpkg/types>
+#include <bpkg/package>
+#include <bpkg/package-odb>
+#include <bpkg/utility>
+#include <bpkg/database>
+#include <bpkg/diagnostics>
+
+#include <bpkg/pkg-disfigure>
+
+using namespace std;
+using namespace butl;
+
+namespace bpkg
+{
+ void
+ pkg_configure (const pkg_configure_options& o, cli::scanner& args)
+ {
+ tracer trace ("pkg_configure");
+
+ 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));
+ transaction t (db.begin ());
+
+ shared_ptr<package> p (db.find<package> (n));
+
+ if (p == nullptr)
+ fail << "package " << n << " does not exist in configuration " << c;
+
+ if (p->state != state::unpacked)
+ fail << "package " << n << " is " << p->state <<
+ info << "expected it to be unpacked";
+
+ level4 ([&]{trace << p->name << " " << p->version;});
+
+ // 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);
+ dir_path out_root (c / dir_path (p->name + "-" + p->version.string ()));
+
+ level4 ([&]{trace << "src_root: " << src_root << ", "
+ << "out_root: " << out_root;});
+
+ // Form the buildspec.
+ //
+ string bspec;
+
+ if (src_root == out_root)
+ bspec = "configure(" + out_root.string () + "/)";
+ else
+ bspec = "configure(" +
+ src_root.string () + "/@" +
+ out_root.string () + "/)";
+
+ level4 ([&]{trace << "buildspec: " << bspec;});
+
+ // Configure.
+ //
+ try
+ {
+ run_b (bspec);
+ }
+ catch (const failed&)
+ {
+ // If we failed to configure the package, make sure we revert
+ // it back to the unpacked state by running disfigure (it is
+ // valid to run disfigure on an un-configured build). And if
+ // disfigure fails as well, then the package will be set into
+ // the broken state.
+ //
+
+ // Pretend we are configured.
+ //
+ p->out_root = out_root.leaf ();
+ p->state = state::configured;
+
+ pkg_disfigure (c, t, p); // Commits the transaction.
+ throw;
+ }
+
+ p->out_root = out_root.leaf ();
+ p->state = state::configured;
+
+ db.update (p);
+ t.commit ();
+
+ if (verb)
+ text << "configured " << p->name << " " << p->version;
+ }
+}
diff --git a/bpkg/pkg-disfigure b/bpkg/pkg-disfigure
new file mode 100644
index 0000000..0e16a40
--- /dev/null
+++ b/bpkg/pkg-disfigure
@@ -0,0 +1,26 @@
+// file : bpkg/pkg-disfigure -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef BPKG_PKG_DISFIGURE
+#define BPKG_PKG_DISFIGURE
+
+#include <bpkg/types>
+#include <bpkg/forward> // transaction, package
+#include <bpkg/pkg-disfigure-options>
+
+namespace bpkg
+{
+ void
+ pkg_disfigure (const pkg_disfigure_options&, cli::scanner& args);
+
+ // Disfigure the package, update its state, and commit the
+ // transaction.
+ //
+ void
+ pkg_disfigure (const dir_path& configuration,
+ transaction&,
+ const shared_ptr<package>&);
+}
+
+#endif // BPKG_PKG_DISFIGURE
diff --git a/bpkg/pkg-disfigure-options.cli b/bpkg/pkg-disfigure-options.cli
new file mode 100644
index 0000000..7e451e8
--- /dev/null
+++ b/bpkg/pkg-disfigure-options.cli
@@ -0,0 +1,32 @@
+// file : bpkg/pkg-disfigure-options.cli
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+include <bpkg/common-options.cli>;
+
+/*
+"\section=1"
+"\name=bpkg-pkg-disfigure"
+
+"\h{SYNOPSIS}
+
+bpkg pkg-disfigure <pkg> [<ver>]"
+
+"\h{DESCRIPTION}
+
+The \cb{pkg-disfigure} command disfigures the previously configured
+(\cb{pkg-configure}) package and returns it to the \cb{unpacked} state."
+*/
+
+namespace bpkg
+{
+ class pkg_disfigure_options: common_options
+ {
+ dir_path --directory|-d (".")
+ {
+ "<dir>",
+ "Assume configuration is in <dir> rather than in the current working
+ directory."
+ };
+ };
+}
diff --git a/bpkg/pkg-disfigure.cxx b/bpkg/pkg-disfigure.cxx
new file mode 100644
index 0000000..7390e76
--- /dev/null
+++ b/bpkg/pkg-disfigure.cxx
@@ -0,0 +1,124 @@
+// file : bpkg/pkg-disfigure.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <bpkg/pkg-disfigure>
+
+#include <bpkg/types>
+#include <bpkg/package>
+#include <bpkg/package-odb>
+#include <bpkg/utility>
+#include <bpkg/database>
+#include <bpkg/diagnostics>
+
+using namespace std;
+using namespace butl;
+
+namespace bpkg
+{
+ void
+ pkg_disfigure (const dir_path& c,
+ transaction& t,
+ const shared_ptr<package>& p)
+ {
+ tracer trace ("pkg_disfigure");
+
+ database& db (t.database ());
+
+ // Calculate package's src_root and out_root.
+ //
+ assert (p->src_root); // Must be set since unpacked.
+ assert (p->out_root); // Must be set since configured.
+
+ dir_path src_root (p->src_root->absolute ()
+ ? *p->src_root
+ : c / *p->src_root);
+ dir_path out_root (c / *p->out_root); // Always relative.
+
+ level4 ([&]{trace << "src_root: " << src_root << ", "
+ << "out_root: " << out_root;});
+
+ // Form the buildspec.
+ //
+ // Why do we need to specify src_root? While it shouldn't be
+ // necessary for a completely configured package, we might
+ // also be called to disfigure a partially configured one.
+ //
+ string bspec;
+
+ if (src_root == out_root)
+ bspec = "disfigure(" + out_root.string () + "/)";
+ else
+ bspec = "disfigure(" +
+ src_root.string () + "/@" +
+ out_root.string () + "/)";
+
+ level4 ([&]{trace << "buildspec: " << bspec;});
+
+ // Disfigure.
+ //
+ try
+ {
+ if (exists (out_root))
+ run_b (bspec);
+
+ // Make sure the out directory is gone unless it is the same as src.
+ //
+ if (out_root != src_root && exists (out_root))
+ fail << "package output directory " << out_root << " still exists";
+ }
+ catch (const failed&)
+ {
+ // If we failed to disfigure the package, set it to the broken
+ // state. The user can then try to clean things up with pkg-purge.
+ //
+ p->state = state::broken;
+ db.update (p);
+ t.commit ();
+
+ info << "package " << p->name << " is now broken; "
+ << "use 'pkg-purge' to remove";
+ throw;
+ }
+
+ p->out_root = optional<dir_path> ();
+ p->state = state::unpacked;
+
+ db.update (p);
+ t.commit ();
+ }
+
+ void
+ pkg_disfigure (const pkg_disfigure_options& o, cli::scanner& args)
+ {
+ tracer trace ("pkg_disfigure");
+
+ dir_path c (o.directory ());
+ level4 ([&]{trace << "configuration: " << c;});
+
+ if (!args.more ())
+ fail << "package name argument expected" <<
+ info << "run 'bpkg help pkg-disfigure' for more information";
+
+ string n (args.next ());
+
+ database db (open (c));
+ transaction t (db.begin ());
+
+ shared_ptr<package> p (db.find<package> (n));
+
+ if (p == nullptr)
+ fail << "package " << n << " does not exist in configuration " << c;
+
+ if (p->state != state::configured)
+ fail << "package " << n << " is " << p->state <<
+ info << "expected it to be configured";
+
+ level4 ([&]{trace << p->name << " " << p->version;});
+
+ pkg_disfigure (c, t, p); // Commits the transaction.
+
+ if (verb)
+ text << "disfigured " << p->name << " " << p->version;
+ }
+}
diff --git a/bpkg/pkg-fetch.cxx b/bpkg/pkg-fetch.cxx
index 9d4efaa..063f0d5 100644
--- a/bpkg/pkg-fetch.cxx
+++ b/bpkg/pkg-fetch.cxx
@@ -13,9 +13,10 @@
#include <bpkg/package-odb>
#include <bpkg/utility>
#include <bpkg/database>
-#include <bpkg/pkg-verify>
#include <bpkg/diagnostics>
+#include <bpkg/pkg-verify>
+
using namespace std;
using namespace butl;
@@ -109,7 +110,9 @@ namespace bpkg
move (a),
purge,
optional<dir_path> (), // No source directory yet.
- false});
+ false,
+ optional<dir_path> () // No output directory yet.
+ });
db.persist (p);
t.commit ();
diff --git a/bpkg/pkg-purge.cxx b/bpkg/pkg-purge.cxx
index 8831b6d..319ec61 100644
--- a/bpkg/pkg-purge.cxx
+++ b/bpkg/pkg-purge.cxx
@@ -78,11 +78,9 @@ namespace bpkg
// First clean up the package source directory.
//
- if (p->source_purge)
+ if (p->purge_src)
{
- dir_path d (*p->source);
- if (d.relative ())
- d = c / d;
+ dir_path d (p->src_root->absolute () ? *p->src_root : c / *p->src_root);
if (p->state != state::broken)
{
@@ -91,8 +89,8 @@ namespace bpkg
if (exists (d)) // Don't complain if someone did our job for us.
rm_r (d);
- p->source = optional<dir_path> ();
- p->source_purge = false;
+ p->src_root = optional<dir_path> ();
+ p->purge_src = false;
}
catch (const failed&)
{
@@ -100,9 +98,8 @@ namespace bpkg
db.update (p);
t.commit ();
- if (verb)
- text << "broke " << p->name << " " << p->version;
-
+ info << "package " << n << " is now broken; "
+ << "use 'pkg-purge --force' to remove";
throw;
}
}
@@ -117,13 +114,24 @@ namespace bpkg
}
}
+ // Also check the output directory of broken packages.
+ //
+ if (p->out_root)
+ {
+ assert (p->state == state::broken); // Can only be present if broken.
+
+ dir_path d (c / *p->out_root); // Always relative.
+
+ if (exists (d))
+ fail << "broken package " << n << " output directory still exists" <<
+ info << "remove " << d << " manually then re-run pkg-purge";
+ }
+
// Now the archive. Pretty much the same code as above but for a file.
//
- if (p->archive_purge && !o.keep ())
+ if (p->purge_archive && !o.keep ())
{
- path a (*p->archive);
- if (a.relative ())
- a = c / a;
+ path a (p->archive->absolute () ? *p->archive : c / *p->archive);
if (p->state != state::broken)
{
@@ -133,7 +141,7 @@ namespace bpkg
rm (a);
p->archive = optional<path> ();
- p->archive_purge = false;
+ p->purge_archive = false;
}
catch (const failed&)
{
@@ -141,9 +149,8 @@ namespace bpkg
db.update (p);
t.commit ();
- if (verb)
- text << "broke " << p->name << " " << p->version;
-
+ info << "package " << n << " is now broken; "
+ << "use 'pkg-purge --force' to remove";
throw;
}
}
diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx
index 3192c27..7116649 100644
--- a/bpkg/pkg-unpack.cxx
+++ b/bpkg/pkg-unpack.cxx
@@ -15,9 +15,10 @@
#include <bpkg/package-odb>
#include <bpkg/utility>
#include <bpkg/database>
-#include <bpkg/pkg-verify>
#include <bpkg/diagnostics>
+#include <bpkg/pkg-verify>
+
using namespace std;
using namespace butl;
@@ -63,10 +64,12 @@ namespace bpkg
move (m.name),
move (m.version),
state::unpacked,
- optional<path> (), // No archive
- false, // Don't purge archive.
+ optional<path> (), // No archive
+ false, // Don't purge archive.
move (ad),
- purge});
+ purge,
+ optional<dir_path> () // No output directory yet.
+ });
db.persist (p);
t.commit ();
@@ -86,7 +89,8 @@ namespace bpkg
fail << "package " << name << " does not exist in configuration " << c;
if (p->state != state::fetched)
- fail << "package " << name << " is already in " << p->state << " state";
+ fail << "package " << name << " is " << p->state <<
+ info << "expected it to be fetched";
level4 ([&]{trace << p->name << " " << p->version;});
@@ -95,9 +99,7 @@ namespace bpkg
// If the archive path is not absolute, then it must be relative
// to the configuration.
//
- path a (*p->archive);
- if (a.relative ())
- a = c / a;
+ path a (p->archive->absolute () ? *p->archive : c / *p->archive);
level4 ([&]{trace << "archive: " << a;});
@@ -155,8 +157,8 @@ namespace bpkg
throw failed ();
}
- p->source = d.leaf (); // For now assuming to be in configuration.
- p->source_purge = true;
+ p->src_root = d.leaf (); // For now assuming to be in configuration.
+ p->purge_src = true;
p->state = state::unpacked;
diff --git a/bpkg/rep-create.cxx b/bpkg/rep-create.cxx
index 9ea24c7..244ef03 100644
--- a/bpkg/rep-create.cxx
+++ b/bpkg/rep-create.cxx
@@ -19,9 +19,10 @@
#include <bpkg/types>
#include <bpkg/utility>
-#include <bpkg/pkg-verify>
#include <bpkg/diagnostics>
+#include <bpkg/pkg-verify>
+
using namespace std;
using namespace butl;
diff --git a/bpkg/test.sh b/bpkg/test.sh
index d71609a..66ff1ad 100755
--- a/bpkg/test.sh
+++ b/bpkg/test.sh
@@ -9,6 +9,7 @@ pkg=libhello
ver=1.0.0
pkga=../../hello/dist/$pkg-$ver.tar.bz2
pkgd=../../hello/dist/$pkg-$ver
+out=$cfg/`basename $pkgd`
function error ()
{
@@ -129,7 +130,7 @@ test pkg-fetch -e $pkga
test pkg-unpack $pkg
test pkg-purge $pkg
stat unknown
-gone $cfg/`basename $pkgd`
+gone $out
# purge unpacked archive but --keep
#
@@ -137,16 +138,16 @@ test pkg-fetch -e $pkga
test pkg-unpack $pkg
test pkg-purge --keep $pkg
stat fetched
-gone $cfg/`basename $pkgd`
+gone $out
test pkg-purge $pkg
# directory --purge
#
cp -r $pkgd $cfg/
-test pkg-unpack -e -p $cfg/`basename $pkgd`
+test pkg-unpack -e -p $out
test pkg-purge $pkg
stat unknown
-gone $cfg/`basename $pkgd`
+gone $out
# archive --purge
#
@@ -155,7 +156,7 @@ test pkg-fetch -e -p $cfg/`basename $pkga`
test pkg-unpack $pkg
test pkg-purge $pkg
stat unknown
-gone $cfg/`basename $pkgd`
+gone $out
gone $cfg/`basename $pkga`
# broken
@@ -163,15 +164,101 @@ gone $cfg/`basename $pkga`
cp $pkga $cfg/
test pkg-fetch -e -p $cfg/`basename $pkga`
test pkg-unpack $pkg
-chmod 000 $cfg/`basename $pkgd`
+chmod 000 $out
fail pkg-purge $pkg
stat broken
fail pkg-purge $pkg # need --force
fail pkg-purge -f -k $pkg # can't keep broken
fail pkg-purge -f $pkg # directory still exists
-chmod 755 $cfg/`basename $pkgd`
-rm -r $cfg/`basename $pkgd`
+chmod 755 $out
+rm -r $out
fail pkg-purge -f $pkg # archive still exists
rm $cfg/`basename $pkga`
test pkg-purge -f $pkg
stat unknown
+
+##
+## pkg-configure/pkg-disfigure
+##
+
+fail pkg-configure # package name expected
+fail pkg-configure config.dist.root=/tmp # ditto
+fail pkg-configure $pkg $pkg # unexpected argument
+fail pkg-configure $pkg # no such package
+
+fail pkg-disfigure # package name expected
+fail pkg-disfigure $pkg # no such package
+
+test pkg-fetch -e $pkga
+
+fail pkg-configure $pkg # wrong package state
+fail pkg-disfigure $pkg # wrong package state
+
+test pkg-purge $pkg
+
+# src == out
+#
+test pkg-fetch -e $pkga
+test pkg-unpack $pkg
+test pkg-configure $pkg
+stat configured
+test pkg-disfigure $pkg
+stat unpacked
+test pkg-purge $pkg
+stat unknown
+
+# src != out
+#
+test pkg-unpack -e $pkgd
+test pkg-configure $pkg
+stat configured
+test pkg-disfigure $pkg
+stat unpacked
+test pkg-purge $pkg
+stat unknown
+gone $out
+
+# out still exists after disfigure
+#
+test pkg-unpack -e $pkgd
+test pkg-configure $pkg
+touch $out/stray
+fail pkg-disfigure $pkg
+stat broken
+rm -r $out
+test pkg-purge -f $pkg
+stat unknown
+
+# disfigure failed
+#
+test pkg-unpack -e $pkgd
+test pkg-configure $pkg
+chmod 555 $out
+fail pkg-disfigure $pkg
+stat broken
+chmod 755 $out
+rm -r $out
+test pkg-purge -f $pkg
+stat unknown
+
+# configure failed but disfigure succeeds
+#
+test pkg-unpack -e $pkgd
+mkdir -p $out/build
+chmod 555 $out/build
+fail pkg-configure $pkg
+stat unpacked
+test pkg-purge $pkg
+stat unknown
+
+# configure and disfigure both failed
+#
+test pkg-unpack -e $pkgd
+mkdir -p $out/build
+chmod 555 $out $out/build # Both to trip configure and disfigure.
+fail pkg-configure $pkg
+stat broken
+chmod 755 $out $out/build
+rm -r $out
+test pkg-purge -f $pkg
+stat unknown