aboutsummaryrefslogtreecommitdiff
path: root/bbot
diff options
context:
space:
mode:
Diffstat (limited to 'bbot')
-rw-r--r--bbot/.gitignore1
-rw-r--r--bbot/build-config53
-rw-r--r--bbot/build-config.cxx125
-rw-r--r--bbot/buildfile37
-rw-r--r--bbot/export41
-rw-r--r--bbot/manifest297
-rw-r--r--bbot/manifest.cxx988
-rw-r--r--bbot/version.in48
8 files changed, 0 insertions, 1590 deletions
diff --git a/bbot/.gitignore b/bbot/.gitignore
deleted file mode 100644
index 088eda4..0000000
--- a/bbot/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-version
diff --git a/bbot/build-config b/bbot/build-config
deleted file mode 100644
index d7a07d9..0000000
--- a/bbot/build-config
+++ /dev/null
@@ -1,53 +0,0 @@
-// file : bbot/build-config -*- C++ -*-
-// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BBOT_BUILD_CONFIG
-#define BBOT_BUILD_CONFIG
-
-#include <string>
-#include <vector>
-#include <iosfwd>
-
-#include <butl/path>
-#include <butl/optional>
-#include <butl/tab-parser>
-#include <butl/target-triplet>
-
-#include <bbot/export>
-#include <bbot/version>
-
-namespace bbot
-{
- // Build configuration matching specific machine names. Used by bbot
- // controllers.
- //
- struct build_config
- {
- std::string machine_pattern; // Machine name pattern.
- std::string name; // Configuration name.
-
- butl::optional<butl::target_triplet> target;
-
- std::vector<std::string> vars;
- };
-
- using build_configs = std::vector<build_config>;
-
- // Parse buildtab stream or file. Throw tab_parsing on parsing error,
- // ios::failure on the underlying OS error.
- //
- // buildtab consists of lines in the following format:
- //
- // <machine-name-pattern> <config-name> [<target>] [<config-vars>]
- //
- using butl::tab_parsing;
-
- LIBBBOT_EXPORT build_configs
- parse_buildtab (std::istream&, const std::string& name);
-
- LIBBBOT_EXPORT build_configs
- parse_buildtab (const butl::path&);
-}
-
-#endif // BBOT_BUILD_CONFIG
diff --git a/bbot/build-config.cxx b/bbot/build-config.cxx
deleted file mode 100644
index 0ee00e9..0000000
--- a/bbot/build-config.cxx
+++ /dev/null
@@ -1,125 +0,0 @@
-// file : bbot/build-config.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <bbot/build-config>
-
-#include <string>
-#include <cstddef> // size_t
-#include <utility> // move()
-#include <stdexcept> // invalid_argument
-
-#include <butl/path>
-#include <butl/fdstream>
-#include <butl/tab-parser>
-
-#include <bbot/manifest> // task_manifest::check_config()
-
-using namespace std;
-using namespace butl;
-
-namespace bbot
-{
- LIBBBOT_EXPORT build_configs
- parse_buildtab (istream& is, const string& name)
- {
- build_configs r;
- tab_parser parser (is, name);
-
- tab_fields tl;
- while (!(tl = parser.next ()).empty ())
- {
- size_t n (tl.size ()); // Fields count.
- size_t i (0); // The field currently being processed.
-
- // Throw tab_parsing for the field currently being processed. If i == n
- // then we refer to the end-of-line column (presumably reporting a missed
- // field).
- //
- auto bad_line = [&name, &tl, &i, n] (const string& d)
- {
- // Offset beyond the end-of-line is meaningless.
- //
- assert (i <= n);
-
- throw tab_parsing (name,
- tl.line,
- i == n
- ? tl.end_column
- : tl[i].column,
- d);
- };
-
- build_config config;
- config.machine_pattern = move (tl[i++].value);
-
- // Configuration name field is a required one.
- //
- if (i == n)
- bad_line ("no configuration name found");
-
- config.name = move (tl[i].value);
-
- // Make sure the name is unique.
- //
- for (const auto& c: r)
- if (c.name == config.name)
- bad_line ("duplicate configuration name");
-
- // If there is no target nor configuration variables then save the
- // configuration and proceed with the next line.
- //
- if (++i == n)
- {
- r.emplace_back (move (config));
- continue;
- }
-
- // If the third field doesn't contain '=' character, then we will treat
- // it as a target.
- //
- if (tl[i].value.find ('=') == string::npos)
- {
- try
- {
- config.target = target_triplet (tl[i].value);
- }
- catch (const invalid_argument& e)
- {
- bad_line (e.what ());
- }
-
- ++i;
- }
-
- try
- {
- for (; i < n; ++i)
- {
- task_manifest::check_config (tl[i].value);
- config.vars.emplace_back (move (tl[i].value));
- }
- }
- catch (const invalid_argument& e)
- {
- bad_line (e.what ());
- }
-
- // Save the configuration.
- //
- r.emplace_back (move (config));
- }
-
- return r;
- }
-
- build_configs
- parse_buildtab (const path& p)
- {
- ifdstream ifs (p);
- build_configs r (parse_buildtab (ifs, p.string ()));
-
- ifs.close (); // Throws on failure.
- return r;
- }
-}
diff --git a/bbot/buildfile b/bbot/buildfile
deleted file mode 100644
index 1c7da48..0000000
--- a/bbot/buildfile
+++ /dev/null
@@ -1,37 +0,0 @@
-# file : bbot/buildfile
-# copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
-# license : MIT; see accompanying LICENSE file
-
-import int_libs = libbutl%lib{butl} libbpkg%lib{bpkg}
-
-lib{bbot}: \
-{hxx cxx}{ build-config } \
-{hxx }{ export } \
-{hxx cxx}{ manifest } \
-{hxx }{ version } \
- $int_libs
-
-hxx{version}: in{version} $src_root/file{manifest}
-hxx{version}: dist = true
-
-# For pre-releases use the complete version to make sure they cannot be used
-# in place of another pre-release or the final version.
-#
-if $version.pre_release
- lib{bbot}: bin.lib.version = @"-$version.project_id"
-else
- lib{bbot}: bin.lib.version = @"-$version.major.$version.minor"
-
-cxx.poptions =+ "-I$out_root" "-I$src_root"
-obja{*}: cxx.poptions += -DLIBBBOT_STATIC_BUILD
-objs{*}: cxx.poptions += -DLIBBBOT_SHARED_BUILD
-
-lib{bbot}: cxx.export.poptions = "-I$out_root" "-I$src_root"
-liba{bbot}: cxx.export.poptions += -DLIBBBOT_STATIC
-libs{bbot}: cxx.export.poptions += -DLIBBBOT_SHARED
-
-lib{bbot}: cxx.export.libs = $int_libs
-
-# Install into the bbot/ subdirectory of, say, /usr/include/.
-#
-install.include = $install.include/bbot/
diff --git a/bbot/export b/bbot/export
deleted file mode 100644
index 6947752..0000000
--- a/bbot/export
+++ /dev/null
@@ -1,41 +0,0 @@
-// file : bbot/export -*- C++ -*-
-// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BBOT_EXPORT
-#define BBOT_EXPORT
-
-// Normally we don't export class templates (but do complete specializations),
-// inline functions, and classes with only inline member functions. Exporting
-// classes that inherit from non-exported/imported bases (e.g., std::string)
-// will end up badly. The only known workarounds are to not inherit or to not
-// export. Also, MinGW GCC doesn't like seeing non-exported function being
-// used before their inline definition. The workaround is to reorder code. In
-// the end it's all trial and error.
-
-#if defined(LIBBBOT_STATIC) // Using static.
-# define LIBBBOT_EXPORT
-#elif defined(LIBBBOT_STATIC_BUILD) // Building static.
-# define LIBBBOT_EXPORT
-#elif defined(LIBBBOT_SHARED) // Using shared.
-# ifdef _WIN32
-# define LIBBBOT_EXPORT __declspec(dllimport)
-# else
-# define LIBBBOT_EXPORT
-# endif
-#elif defined(LIBBBOT_SHARED_BUILD) // Building shared.
-# ifdef _WIN32
-# define LIBBBOT_EXPORT __declspec(dllexport)
-# else
-# define LIBBBOT_EXPORT
-# endif
-#else
-// If none of the above macros are defined, then we assume we are being used
-// by some third-party build system that cannot/doesn't signal the library
-// type. Note that this fallback works for both static and shared but in case
-// of shared will be sub-optimal compared to having dllimport.
-//
-# define LIBBBOT_EXPORT // Using static or shared.
-#endif
-
-#endif // BBOT_EXPORT
diff --git a/bbot/manifest b/bbot/manifest
deleted file mode 100644
index 115d9b6..0000000
--- a/bbot/manifest
+++ /dev/null
@@ -1,297 +0,0 @@
-// file : bbot/manifest -*- C++ -*-
-// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef BBOT_MANIFEST
-#define BBOT_MANIFEST
-
-#include <string>
-#include <vector>
-#include <ostream>
-
-#include <butl/optional>
-#include <butl/target-triplet>
-#include <butl/manifest-forward>
-
-#include <bpkg/manifest> // version, repository_location
-
-#include <bbot/export>
-#include <bbot/version>
-
-namespace bbot
-{
- using strings = std::vector<std::string>;
-
- class LIBBBOT_EXPORT machine_header_manifest
- {
- public:
- std::string id;
- std::string name;
- std::string summary;
-
- machine_header_manifest (std::string i, std::string n, std::string s)
- : id (std::move (i)), name (std::move (n)), summary (std::move (s)) {}
-
- public:
- machine_header_manifest () = default; // VC export.
- machine_header_manifest (butl::manifest_parser&,
- bool ignore_unknown = false);
- machine_header_manifest (butl::manifest_parser&,
- butl::manifest_name_value start,
- bool ignore_unknown = false);
-
- void
- serialize (butl::manifest_serializer&) const;
- };
-
- using machine_header_manifests = std::vector<machine_header_manifest>;
-
- class LIBBBOT_EXPORT task_request_manifest
- {
- public:
- std::string agent;
-
- // Agent's public key SHA256 fingerprint.
- //
- // @@ How the fingerpring for openssl public key will be produced? Seems
- // there is no "standard" for it. Possibly we will use the following
- // command result (plain SHA256).
- //
- // $ cat key.pub | openssl sha256
- //
- butl::optional<std::string> fingerprint;
-
- machine_header_manifests machines;
-
- task_request_manifest (std::string a,
- butl::optional<std::string> f,
- machine_header_manifests m)
- : agent (std::move (a)),
- fingerprint (std::move (f)),
- machines (std::move (m)) {}
-
- public:
- task_request_manifest () = default; // VC export.
- task_request_manifest (butl::manifest_parser&,
- bool ignore_unknown = false);
-
- void
- serialize (butl::manifest_serializer&) const;
- };
-
- class LIBBBOT_EXPORT task_manifest
- {
- public:
- // Package to build.
- //
- std::string name;
- bpkg::version version;
- bpkg::repository_location repository; // Remote or absolute.
-
- // The SHA256 repositories certificates fingerprints to trust. The special
- // 'yes' value can be specified instead of fingerprint (in which case all
- // repositories will be trusted without authentication).
- //
- strings trust;
-
- // Build machine to use for building the package.
- //
- std::string machine;
-
- // Default for the machine if absent.
- //
- butl::optional<butl::target_triplet> target;
-
- // Build system configuration variables (in addition to build environment
- // configuration variables).
- // Note: could be quoted.
- //
- strings config;
-
- strings
- unquoted_config () const;
-
- task_manifest (std::string nm,
- bpkg::version vr,
- bpkg::repository_location rl,
- strings tr,
- std::string mn,
- butl::optional<butl::target_triplet> tg,
- strings cf)
- : name (std::move (nm)),
- version (std::move (vr)),
- repository (std::move (rl)),
- trust (tr),
- machine (std::move (mn)),
- target (std::move (tg)),
- config (std::move (cf)) {}
-
- public:
- task_manifest () = default; // VC export.
- task_manifest (butl::manifest_parser&, bool ignore_unknown = false);
- task_manifest (butl::manifest_parser&,
- butl::manifest_name_value start,
- bool ignore_unknown = false);
-
- void
- serialize (butl::manifest_serializer&) const;
-
- // Check that a string has the name=value format. The name must not
- // contain spaces. Throw invalid_argument if the string doesn't conform to
- // these rules.
- //
- static void
- check_config (const std::string&);
- };
-
- class LIBBBOT_EXPORT task_response_manifest
- {
- public:
- // If empty then no task available.
- //
- std::string session;
-
- // Challenge, result url and task are absent if session is empty.
- //
- butl::optional<std::string> challenge;
- butl::optional<std::string> result_url;
- butl::optional<task_manifest> task;
-
- task_response_manifest (std::string s,
- butl::optional<std::string> c,
- butl::optional<std::string> u,
- butl::optional<task_manifest> t)
- : session (std::move (s)),
- challenge (std::move (c)),
- result_url (std::move (u)),
- task (std::move (t)) {}
-
- public:
- task_response_manifest () = default; // VC export.
- task_response_manifest (butl::manifest_parser&,
- bool ignore_unknown = false);
-
- void
- serialize (butl::manifest_serializer&) const;
- };
-
- // Build task or operation result status.
- //
- enum class result_status: std::uint8_t
- {
- // The order of the enumerators is arranged so that their integral values
- // indicate whether one "overrides" the other in the "merge" operator|
- // (see below).
- //
- success,
- warning,
- error,
- abort,
- abnormal
- };
-
- LIBBBOT_EXPORT std::string
- to_string (result_status);
-
- LIBBBOT_EXPORT result_status
- to_result_status (const std::string&); // May throw invalid_argument.
-
- inline std::ostream&
- operator<< (std::ostream& os, result_status s) {return os << to_string (s);}
-
- inline result_status&
- operator|= (result_status& l, result_status r)
- {
- if (static_cast<std::uint8_t> (r) > static_cast<std::uint8_t> (l))
- l = r;
- return l;
- }
-
- // Return true if the result is "bad", that is, error or worse.
- //
- inline bool
- operator! (result_status s)
- {
- return static_cast<std::uint8_t> (s) >=
- static_cast<std::uint8_t> (result_status::error);
- }
-
- struct operation_result
- {
- std::string operation; // "configure", "update", "test", etc.
- result_status status;
- std::string log;
- };
-
- using operation_results = std::vector<operation_result>;
-
- class LIBBBOT_EXPORT result_manifest
- {
- public:
- // Built package.
- //
- // If the version is 0 (which signifies a stub package that cannot be
- // possibly built) then both name and version are "unknown". This is used
- // by the worker to signal abnormal termination before being able to
- // obtain the package name/version.
- //
- std::string name;
- bpkg::version version;
-
- result_status status;
-
- // Ordered (ascending) by operation value. May not contain all the
- // operations if the task failed in the middle, but should have no gaps
- // (operation can not start unless all previous ones succeeded).
- //
- operation_results results;
-
- result_manifest (std::string n,
- bpkg::version v,
- result_status s,
- operation_results r)
- : name (std::move (n)),
- version (std::move (v)),
- status (s),
- results (std::move (r)) {}
-
- public:
- result_manifest () = default; // VC export.
- result_manifest (butl::manifest_parser&, bool ignore_unknown = false);
- result_manifest (butl::manifest_parser&,
- butl::manifest_name_value start,
- bool ignore_unknown = false);
-
- void
- serialize (butl::manifest_serializer&) const;
- };
-
- class LIBBBOT_EXPORT result_request_manifest
- {
- public:
- std::string session; // The task response session.
-
- // The answer to challenge in the task response.
- //
- butl::optional<std::string> challenge;
-
- result_manifest result;
-
- result_request_manifest (std::string s,
- butl::optional<std::string> c,
- result_manifest r)
- : session (std::move (s)),
- challenge (std::move (c)),
- result (std::move (r)) {}
-
- public:
- result_request_manifest () = default; // VC export.
- result_request_manifest (butl::manifest_parser&,
- bool ignore_unknown = false);
-
- void
- serialize (butl::manifest_serializer&) const;
- };
-}
-
-#endif // BBOT_MANIFEST
diff --git a/bbot/manifest.cxx b/bbot/manifest.cxx
deleted file mode 100644
index eab563b..0000000
--- a/bbot/manifest.cxx
+++ /dev/null
@@ -1,988 +0,0 @@
-// file : bbot/manifest.cxx -*- C++ -*-
-// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#include <bbot/manifest>
-
-#include <vector>
-#include <string>
-#include <cctype> // isxdigit()
-#include <cassert>
-#include <sstream>
-#include <cstddef> // size_t
-#include <utility> // move()
-#include <cstdint> // uint64_t
-#include <stdexcept> // invalid_argument
-
-#include <butl/utility> // digit()
-#include <butl/tab-parser>
-#include <butl/string-parser>
-#include <butl/manifest-parser>
-#include <butl/manifest-serializer>
-
-using namespace std;
-using namespace butl;
-using namespace bpkg;
-
-namespace bbot
-{
- using parser = manifest_parser;
- using parsing = manifest_parsing;
- using serializer = manifest_serializer;
- using serialization = manifest_serialization;
- using name_value = manifest_name_value;
-
- using strings = vector<string>;
-
- // result_status
- //
- string
- to_string (result_status s)
- {
- switch (s)
- {
- case result_status::success: return "success";
- case result_status::warning: return "warning";
- case result_status::error: return "error";
- case result_status::abort: return "abort";
- case result_status::abnormal: return "abnormal";
- }
-
- assert (false);
- return string ();
- }
-
- result_status
- to_result_status (const string& s)
- {
- if (s == "success") return result_status::success;
- else if (s == "warning") return result_status::warning;
- else if (s == "error") return result_status::error;
- else if (s == "abort") return result_status::abort;
- else if (s == "abnormal") return result_status::abnormal;
- else throw invalid_argument ("invalid result status '" + s + "'");
- }
-
- // Utility functions
- //
- inline static bool
- valid_sha256 (const string& s) noexcept
- {
- if (s.size () != 64)
- return false;
-
- for (const auto& c: s)
- {
- if ((c < 'a' || c > 'f' ) && !digit (c))
- return false;
- }
-
- return true;
- }
-
- inline static bool
- valid_fingerprint (const string& f) noexcept
- {
- size_t n (f.size ());
- if (n != 32 * 3 - 1)
- return false;
-
- for (size_t i (0); i < n; ++i)
- {
- char c (f[i]);
- if ((i + 1) % 3 == 0)
- {
- if (c != ':')
- return false;
- }
- else if (!isxdigit (c))
- return false;
- }
-
- return true;
- }
-
- // machine_header_manifest
- //
- machine_header_manifest::
- machine_header_manifest (parser& p, bool iu)
- : machine_header_manifest (p, p.next (), iu)
- {
- // Make sure this is the end.
- //
- name_value nv (p.next ());
- if (!nv.empty ())
- throw parsing (p.name (), nv.name_line, nv.name_column,
- "single machine header manifest expected");
- }
-
- machine_header_manifest::
- machine_header_manifest (parser& p, name_value nv, bool iu)
- {
- auto bad_name = [&p, &nv] (const string& d)
- {
- throw parsing (p.name (), nv.name_line, nv.name_column, d);
- };
-
- auto bad_value = [&p, &nv] (const string& d)
- {
- throw parsing (p.name (), nv.value_line, nv.value_column, d);
- };
-
- // Make sure this is the start and we support the version.
- //
- if (!nv.name.empty ())
- bad_name ("start of machine header manifest expected");
-
- if (nv.value != "1")
- bad_value ("unsupported format version");
-
- for (nv = p.next (); !nv.empty (); nv = p.next ())
- {
- string& n (nv.name);
- string& v (nv.value);
-
- if (n == "id")
- {
- if (!id.empty ())
- bad_name ("machine id redefinition");
-
- if (v.empty ())
- bad_value ("empty machine id");
-
- id = move (v);
- }
- else if (n == "name")
- {
- if (!name.empty ())
- bad_name ("machine name redefinition");
-
- if (v.empty ())
- bad_value ("empty machine name");
-
- name = move (v);
- }
- else if (n == "summary")
- {
- if (!summary.empty ())
- bad_name ("machine summary redefinition");
-
- if (v.empty ())
- bad_value ("empty machine summary");
-
- summary = move (v);
- }
- else if (!iu)
- bad_name ("unknown name '" + n + "' in machine header manifest");
- }
-
- // Verify all non-optional values were specified.
- //
- if (id.empty ())
- bad_value ("no machine id specified");
-
- if (name.empty ())
- bad_value ("no machine name specified");
-
- if (summary.empty ())
- bad_value ("no machine summary specified");
- }
-
- void machine_header_manifest::
- serialize (serializer& s) const
- {
- // @@ Should we check that all non-optional values are specified and all
- // values are valid?
- //
- s.next ("", "1"); // Start of manifest.
- s.next ("id", id);
- s.next ("name", name);
- s.next ("summary", summary);
- s.next ("", ""); // End of manifest.
- }
-
- // task_request_manifest
- //
- task_request_manifest::
- task_request_manifest (parser& p, bool iu)
- {
- name_value nv (p.next ());
-
- auto bad_name = [&p, &nv] (const string& d)
- {
- throw parsing (p.name (), nv.name_line, nv.name_column, d);
- };
-
- auto bad_value = [&p, &nv] (const string& d)
- {
- throw parsing (p.name (), nv.value_line, nv.value_column, d);
- };
-
- // Make sure this is the start and we support the version.
- //
- if (!nv.name.empty ())
- bad_name ("start of task request manifest expected");
-
- if (nv.value != "1")
- bad_value ("unsupported format version");
-
- // Parse the task request manifest.
- //
- for (nv = p.next (); !nv.empty (); nv = p.next ())
- {
- string& n (nv.name);
- string& v (nv.value);
-
- if (n == "agent")
- {
- if (!agent.empty ())
- bad_name ("task request agent redefinition");
-
- if (v.empty ())
- bad_value ("empty task request agent");
-
- agent = move (v);
- }
- else if (n == "fingerprint")
- {
- if (fingerprint)
- bad_name ("task request fingerprint redefinition");
-
- if (!valid_sha256 (v))
- bad_value ("invalid task request fingerprint");
-
- fingerprint = move (v);
- }
- else if (!iu)
- bad_name ("unknown name '" + n + "' in task request manifest");
- }
-
- // Verify all non-optional values were specified.
- //
- if (agent.empty ())
- bad_value ("no task request agent specified");
-
- // Parse machine header manifests.
- //
- for (nv = p.next (); !nv.empty (); nv = p.next ())
- machines.emplace_back (machine_header_manifest (p, nv, iu));
-
- if (machines.empty ())
- bad_value ("no task request machines specified");
- }
-
- void task_request_manifest::
- serialize (serializer& s) const
- {
- // @@ Should we check that all non-optional values are specified and all
- // values are valid?
- //
- s.next ("", "1"); // Start of manifest.
- s.next ("agent", agent);
-
- if (fingerprint)
- s.next ("fingerprint", *fingerprint);
-
- s.next ("", ""); // End of manifest.
-
- for (const machine_header_manifest& m: machines)
- m.serialize (s);
-
- s.next ("", ""); // End of stream.
- }
-
- // task_manifest
- //
- task_manifest::
- task_manifest (parser& p, bool iu)
- : task_manifest (p, p.next (), iu)
- {
- // Make sure this is the end.
- //
- name_value nv (p.next ());
- if (!nv.empty ())
- throw parsing (p.name (), nv.name_line, nv.name_column,
- "single task manifest expected");
- }
-
- task_manifest::
- task_manifest (parser& p, name_value nv, bool iu)
- {
- auto bad_name = [&p, &nv] (const string& d)
- {
- throw parsing (p.name (), nv.name_line, nv.name_column, d);
- };
-
- // Offsets are used to tie an error to the specific position inside a
- // manifest value (possibly a multiline one).
- //
- auto bad_value = [&p, &nv] (
- const string& d, uint64_t column_offset = 0, uint64_t line_offset = 0)
- {
- throw parsing (p.name (),
- nv.value_line + line_offset,
- (line_offset == 0 ? nv.value_column : 1) + column_offset,
- d);
- };
-
- // Make sure this is the start and we support the version.
- //
- if (!nv.name.empty ())
- bad_name ("start of task manifest expected");
-
- if (nv.value != "1")
- bad_value ("unsupported format version");
-
- // Parse the task manifest.
- //
- for (nv = p.next (); !nv.empty (); nv = p.next ())
- {
- string& n (nv.name);
- string& v (nv.value);
-
- if (n == "name")
- {
- if (!name.empty ())
- bad_name ("task package name redefinition");
-
- if (v.empty ())
- bad_value ("empty task package name");
-
- name = move (v);
- }
- else if (n == "version")
- {
- if (!version.empty ())
- bad_name ("task package version redefinition");
-
- try
- {
- version = bpkg::version (move (v));
- }
- catch (const invalid_argument& e)
- {
- bad_value (string ("invalid task package version: ") + e.what ());
- }
-
- // Versions like 1.2.3- are forbidden in manifest as intended to be
- // used for version constrains rather than actual releases.
- //
- if (version.release && version.release->empty ())
- bad_value ("invalid task package version release");
- }
- else if (n == "repository")
- {
- if (!repository.empty ())
- bad_name ("task repository redefinition");
-
- if (v.empty ())
- bad_value ("empty task repository");
-
- try
- {
- // Call remote/absolute repository location constructor (throws
- // invalid_argument for relative location).
- //
- repository = repository_location (move (v));
- }
- catch (const invalid_argument& e)
- {
- bad_value (string ("invalid task repository: ") + e.what ());
- }
- }
- else if (n == "trust")
- {
- if (v != "yes" && !valid_fingerprint (v))
- bad_value ("invalid repository certificate fingerprint");
-
- trust.emplace_back (move (v));
- }
- else if (n == "machine")
- {
- if (!machine.empty ())
- bad_name ("task machine redefinition");
-
- if (v.empty ())
- bad_value ("empty task machine");
-
- machine = move (v);
- }
- else if (n == "target")
- {
- if (target)
- bad_name ("task target redefinition");
-
- try
- {
- target = target_triplet (v);
- }
- catch (const invalid_argument& e)
- {
- bad_value (string ("invalid task target: ") + e.what ());
- }
- }
- else if (n == "config")
- {
- if (!config.empty ())
- bad_name ("task configuration redefinition");
-
- // Note that when reporting errors we combine the manifest value
- // position with the respective field and error positions.
- //
- try
- {
- istringstream is (v);
- tab_parser parser (is, "");
-
- // Here we naturally support multiline config manifest.
- //
- tab_fields tl;
- while (!(tl = parser.next ()).empty ())
- {
- for (auto& tf: tl)
- {
- try
- {
- check_config (tf.value);
- }
- catch (const invalid_argument& e)
- {
- bad_value (string ("invalid task configuration: ") + e.what (),
- tf.column - 1,
- tl.line - 1);
- }
-
- config.emplace_back (move (tf.value));
- }
- }
- }
- catch (const tab_parsing& e)
- {
- bad_value ("invalid task configuration: " + e.description,
- e.column - 1,
- e.line - 1);
- }
-
- if (config.empty ())
- bad_value ("empty task configuration");
- }
- else if (!iu)
- bad_name ("unknown name '" + n + "' in task manifest");
- }
-
- // Verify all non-optional values were specified.
- //
- if (name.empty ())
- bad_value ("no task package name specified");
-
- if (version.empty ())
- bad_value ("no task package version specified");
-
- if (repository.empty ())
- bad_value ("no task repository specified");
-
- if (machine.empty ())
- bad_value ("no task machine specified");
- }
-
- void task_manifest::
- serialize (serializer& s) const
- {
- // @@ Should we check that all non-optional values are specified and all
- // values are valid?
- //
- s.next ("", "1"); // Start of manifest.
- s.next ("name", name);
- s.next ("version", version.string ());
- s.next ("repository", repository.string ());
-
- for (const auto& v: trust)
- s.next ("trust", v);
-
- s.next ("machine", machine);
-
- if (target)
- s.next ("target", target->string ());
-
- // Recompose config string as a space-separated variable list,
- //
- if (!config.empty ())
- {
- string v;
- for (auto b (config.cbegin ()), i (b), e (config.cend ()); i != e; ++i)
- {
- if (i != b)
- v += ' ';
-
- v += *i;
- }
-
- s.next ("config", v);
- }
-
- s.next ("", ""); // End of manifest.
- }
-
- strings task_manifest::
- unquoted_config () const
- {
- return string_parser::unquote (config);
- }
-
- void task_manifest::
- check_config (const string& s)
- {
- auto i (s.begin ());
- auto e (s.end ());
-
- // Iterate until the variable name end and check that it contains no
- // whitespaces.
- //
- for (; i != e; ++i)
- {
- char c (*i);
-
- if (c == ' ' || c == '\t') // Whitespace in name.
- throw invalid_argument ("expected variable assignment");
- else if (c == '=')
- break;
- }
-
- if (i == e)
- throw invalid_argument ("no variable value");
- }
-
- // task_response_manifest
- //
- task_response_manifest::
- task_response_manifest (parser& p, bool iu)
- {
- name_value nv (p.next ());
-
- auto bad_name = [&p, &nv] (const string& d)
- {
- throw parsing (p.name (), nv.name_line, nv.name_column, d);
- };
-
- auto bad_value = [&p, &nv] (const string& d)
- {
- throw parsing (p.name (), nv.value_line, nv.value_column, d);
- };
-
- // Make sure this is the start and we support the version.
- //
- if (!nv.name.empty ())
- bad_name ("start of task response manifest expected");
-
- if (nv.value != "1")
- bad_value ("unsupported format version");
-
- // Parse the task response manifest.
- //
- // Note that we need to distinguish an empty and absent session.
- //
- optional<string> sess;
- for (nv = p.next (); !nv.empty (); nv = p.next ())
- {
- string& n (nv.name);
- string& v (nv.value);
-
- if (n == "session")
- {
- if (sess)
- bad_name ("task response session redefinition");
-
- sess = move (v);
- }
- else if (n == "challenge")
- {
- if (challenge)
- bad_name ("task response challenge redefinition");
-
- if (v.empty ())
- bad_value ("empty task response challenge");
-
- challenge = move (v);
- }
- else if (n == "result-url")
- {
- if (result_url)
- bad_name ("task response result url redefinition");
-
- if (v.empty ())
- bad_value ("empty task response result url");
-
- result_url = move (v);
- }
- else if (!iu)
- bad_name ("unknown name '" + n + "' in task response manifest");
- }
-
- // Verify all non-optional values were specified, and all values are
- // expected.
- //
- if (!sess)
- bad_value ("no task response session specified");
-
- session = move (*sess);
-
- // If session is not empty then the challenge may, and the result url
- // must, be present, otherwise they shouldn't.
- //
- if (!session.empty ())
- {
- if (!result_url)
- bad_value ("no task response result url specified");
- }
- else
- {
- if (challenge)
- bad_value ("unexpected task response challenge");
-
- if (result_url)
- bad_value ("unexpected task response result url");
- }
-
- // If session is not empty then the task manifest must follow, otherwise it
- // shouldn't.
- //
- nv = p.next ();
-
- if (!session.empty ())
- {
- if (nv.empty ())
- bad_value ("task manifest expected");
-
- task = task_manifest (p, nv, iu);
-
- nv = p.next ();
- }
-
- // Make sure this is the end.
- //
- if (!nv.empty ())
- throw parsing (p.name (), nv.name_line, nv.name_column,
- "single task response manifest expected");
- }
-
- void task_response_manifest::
- serialize (serializer& s) const
- {
- // @@ Should we check that all non-optional values are specified and all
- // values are valid?
- //
- s.next ("", "1"); // Start of manifest.
- s.next ("session", session);
-
- if (challenge)
- s.next ("challenge", *challenge);
-
- if (result_url)
- s.next ("result-url", *result_url);
-
- s.next ("", ""); // End of manifest.
-
- if (task)
- task->serialize (s);
-
- s.next ("", ""); // End of stream.
- }
-
- // result_manifest
- //
- result_manifest::
- result_manifest (parser& p, bool iu)
- : result_manifest (p, p.next (), iu)
- {
- // Make sure this is the end.
- //
- name_value nv (p.next ());
- if (!nv.empty ())
- throw parsing (p.name (), nv.name_line, nv.name_column,
- "single result manifest expected");
- }
-
- result_manifest::
- result_manifest (parser& p, name_value nv, bool iu)
- {
- auto bad_name = [&p, &nv] (const string& d)
- {
- throw parsing (p.name (), nv.name_line, nv.name_column, d);
- };
-
- auto bad_value = [&p, &nv] (const string& d, size_t offset = 0)
- {
- throw parsing (p.name (), nv.value_line, nv.value_column + offset, d);
- };
-
- auto result_stat =
- [&bad_value] (const string& v, const string& what) -> result_status
- {
- try
- {
- return to_result_status (v);
- }
- catch (const invalid_argument&)
- {
- bad_value ("invalid " + what);
- }
-
- // Can't be here. Would be redundant if it were possible to declare
- // lambda with the [[noreturn]] attribute. Note that GCC (non-portably)
- // supports that.
- //
- return result_status::abnormal;
- };
-
- // Make sure this is the start and we support the version.
- //
- if (!nv.name.empty ())
- bad_name ("start of result manifest expected");
-
- if (nv.value != "1")
- bad_value ("unsupported format version");
-
- // Parse the result manifest.
- //
- optional<result_status> stat;
-
- // Number of parsed *-log values. Also denotes the next expected log type.
- //
- size_t nlog (0);
-
- for (nv = p.next (); !nv.empty (); nv = p.next ())
- {
- string& n (nv.name);
- string& v (nv.value);
-
- if (n == "name")
- {
- if (!name.empty ())
- bad_name ("result package name redefinition");
-
- if (v.empty ())
- bad_value ("empty result package name");
-
- name = move (v);
- }
- else if (n == "version")
- {
- if (!version.empty ())
- bad_name ("result package version redefinition");
-
- try
- {
- version = bpkg::version (move (v));
- }
- catch (const invalid_argument& e)
- {
- bad_value (string ("invalid result package version: ") + e.what ());
- }
-
- // Versions like 1.2.3- are forbidden in manifest as intended to be
- // used for version constrains rather than actual releases.
- //
- if (version.release && version.release->empty ())
- bad_value ("invalid result package version release");
- }
- else if (n == "status")
- {
- if (stat)
- bad_name ("result status redefinition");
-
- stat = result_stat (v, "result status");
- }
- else
- {
- size_t nn (n.size ()); // Name length.
-
- // Note: returns false if nothing preceeds a suffix.
- //
- auto suffix = [&n, nn] (const char* s, size_t sn) -> bool
- {
- return nn > sn && n.compare (nn - sn, sn, s) == 0;
- };
-
- size_t sn;
- if (suffix ("-status", sn = 7))
- {
- if (!stat)
- bad_name ("result status must appear first");
-
- if (nlog > 0) // Some logs have already been parsed.
- bad_name (n + " after operations logs");
-
- string op (n, 0, nn - sn);
-
- // Make sure the operation result status is not redefined.
- //
- for (const auto& r: results)
- {
- if (r.operation == op)
- bad_name ("result " + n + " redefinition");
- }
-
- // Add the operation result (log will come later).
- //
- results.push_back ({move (op), result_stat (v, n), string ()});
- }
- else if (suffix ("-log", sn = 4))
- {
- string op (n, 0, nn - sn);
-
- // Check that specifically this operation log is expected.
- //
- if (nlog >= results.size ())
- bad_name ("unexpected " + n);
-
- if (results[nlog].operation != op)
- bad_name (results[nlog].operation + "-log is expected");
-
- // Save operation log.
- //
- results[nlog++].log = move (v);
- }
- else if (!iu)
- bad_name ("unknown name '" + n + "' in result manifest");
- }
- }
-
- // Verify all non-optional values were specified.
- //
- if (name.empty ())
- bad_value ("no result package name specified");
-
- if (version.empty ())
- bad_value ("no result package version specified");
-
- if (!stat)
- bad_value ("no result status specified");
-
- // @@ Checking that the result status is consistent with operations
- // statuses is a bit hairy, so let's postpone for now.
- //
- status = move (*stat);
-
- // Check that we have log for every operation result status.
- //
- if (nlog < results.size ())
- bad_name ("no result " + results[nlog].operation + "-log specified");
- }
-
- void result_manifest::
- serialize (serializer& s) const
- {
- // @@ Should we check that all non-optional values are specified and all
- // values are valid?
- //
- s.next ("", "1"); // Start of manifest.
- s.next ("name", name);
- s.next ("version", version.string ());
- s.next ("status", to_string (status));
-
- // Serialize *-status values.
- //
- for (const auto& r: results)
- s.next (r.operation + "-status", to_string (r.status));
-
- // Serialize *-log values.
- //
- for (const auto& r: results)
- s.next (r.operation + "-log", r.log);
-
- s.next ("", ""); // End of manifest.
- }
-
- // result_request_manifest
- //
- result_request_manifest::
- result_request_manifest (parser& p, bool iu)
- {
- name_value nv (p.next ());
-
- auto bad_name = [&p, &nv] (const string& d)
- {
- throw parsing (p.name (), nv.name_line, nv.name_column, d);
- };
-
- auto bad_value = [&p, &nv] (const string& d)
- {
- throw parsing (p.name (), nv.value_line, nv.value_column, d);
- };
-
- // Make sure this is the start and we support the version.
- //
- if (!nv.name.empty ())
- bad_name ("start of result request manifest expected");
-
- if (nv.value != "1")
- bad_value ("unsupported format version");
-
- // Parse the result request manifest.
- //
- for (nv = p.next (); !nv.empty (); nv = p.next ())
- {
- string& n (nv.name);
- string& v (nv.value);
-
- if (n == "session")
- {
- if (!session.empty ())
- bad_name ("result request session redefinition");
-
- if (v.empty ())
- bad_value ("empty result request session");
-
- session = move (v);
- }
- else if (n == "challenge")
- {
- if (challenge)
- bad_name ("result request challenge redefinition");
-
- if (v.empty ())
- bad_value ("empty result request challenge");
-
- challenge = move (v);
- }
- else if (!iu)
- bad_name ("unknown name '" + n + "' in result request manifest");
- }
-
- // Verify all non-optional values were specified.
- //
- if (session.empty ())
- bad_value ("no result request session specified");
-
- nv = p.next ();
- if (nv.empty ())
- bad_value ("result manifest expected");
-
- result = result_manifest (p, nv, iu);
-
- // Make sure this is the end.
- //
- nv = p.next ();
- if (!nv.empty ())
- throw parsing (p.name (), nv.name_line, nv.name_column,
- "single result request manifest expected");
- }
-
- void result_request_manifest::
- serialize (serializer& s) const
- {
- // @@ Should we check that all non-optional values are specified and all
- // values are valid?
- //
- s.next ("", "1"); // Start of manifest.
- s.next ("session", session);
-
- if (challenge)
- s.next ("challenge", *challenge);
-
- s.next ("", ""); // End of manifest.
-
- result.serialize (s);
- s.next ("", ""); // End of stream.
- }
-}
diff --git a/bbot/version.in b/bbot/version.in
deleted file mode 100644
index 41c4ce6..0000000
--- a/bbot/version.in
+++ /dev/null
@@ -1,48 +0,0 @@
-// file : bbot/version.in -*- C++ -*-
-// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
-// license : MIT; see accompanying LICENSE file
-
-#ifndef LIBBBOT_VERSION // Note: using the version macro itself.
-
-// Note: using build2 standard versioning scheme. The numeric version format
-// is AAABBBCCCDDDE where:
-//
-// AAA - major version number
-// BBB - minor version number
-// CCC - bugfix version number
-// DDD - alpha / beta (DDD + 500) version number
-// E - final (0) / snapshot (1)
-//
-// When DDDE is not 0, 1 is subtracted from AAABBBCCC. For example:
-//
-// Version AAABBBCCCDDDE
-//
-// 0.1.0 0000010000000
-// 0.1.2 0000010010000
-// 1.2.3 0010020030000
-// 2.2.0-a.1 0020019990010
-// 3.0.0-b.2 0029999995020
-// 2.2.0-a.1.z 0020019990011
-//
-#define LIBBBOT_VERSION $libbbot.version.project_number$ULL
-#define LIBBBOT_VERSION_STR "$libbbot.version.project$"
-#define LIBBBOT_VERSION_ID "$libbbot.version.project_id$"
-
-#define LIBBBOT_VERSION_MAJOR $libbbot.version.major$
-#define LIBBBOT_VERSION_MINOR $libbbot.version.minor$
-#define LIBBBOT_VERSION_PATCH $libbbot.version.patch$
-
-#define LIBBBOT_PRE_RELEASE $libbbot.version.pre_release$
-
-#define LIBBBOT_SNAPSHOT $libbbot.version.snapshot_sn$ULL
-#define LIBBBOT_SNAPSHOT_ID "$libbbot.version.snapshot_id$"
-
-#include <butl/version>
-
-$libbutl.check(LIBBUTL_VERSION, LIBBUTL_SNAPSHOT)$
-
-#include <bpkg/version>
-
-$libbpkg.check(LIBBPKG_VERSION, LIBBPKG_SNAPSHOT)$
-
-#endif // LIBBBOT_VERSION