aboutsummaryrefslogtreecommitdiff
path: root/bpkg/pkg-disfigure.cxx
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 /bpkg/pkg-disfigure.cxx
parent299c4e373d2c2642a8e4c3537eb0436c5a6b9c09 (diff)
Implement pkg-{configure, disfigure} commands
Diffstat (limited to 'bpkg/pkg-disfigure.cxx')
-rw-r--r--bpkg/pkg-disfigure.cxx124
1 files changed, 124 insertions, 0 deletions
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;
+ }
+}