Line data Source code
1 : /*! 2 : * \file esys/repo/buildinfo.cpp 3 : * \brief 4 : * 5 : * \cond 6 : * __legal_b__ 7 : * 8 : * Copyright (c) 2026 Michel Gillet 9 : * Distributed under the MIT License. 10 : * (See accompanying file LICENSE.txt or 11 : * copy at https://opensource.org/licenses/MIT) 12 : * 13 : * __legal_e__ 14 : * \endcond 15 : * 16 : */ 17 : 18 : #include "esys/repo/esysrepo_prec.h" 19 : #include "esys/repo/buildinfo.h" 20 : 21 : #include <iomanip> 22 : #include <sstream> 23 : 24 : namespace esys::repo 25 : { 26 : 27 0 : BuildInfo &BuildInfo::get() 28 : { 29 0 : static BuildInfo instance; 30 0 : return instance; 31 : } 32 : 33 0 : void BuildInfo::clear() 34 : { 35 0 : m_embedded = false; 36 0 : m_tagged = false; 37 0 : m_public_version.clear(); 38 0 : m_product_version.clear(); 39 0 : m_version4.clear(); 40 0 : m_build_id.clear(); 41 0 : m_git_sha.clear(); 42 0 : m_git_short_sha.clear(); 43 0 : m_git_ref.clear(); 44 0 : m_git_tag.clear(); 45 0 : m_pipeline_id.clear(); 46 0 : m_pipeline_iid.clear(); 47 0 : m_job_id.clear(); 48 0 : m_build_date_utc.clear(); 49 0 : m_dependencies.clear(); 50 0 : } 51 : 52 0 : void BuildInfo::set_embedded(bool embedded) 53 : { 54 0 : m_embedded = embedded; 55 0 : } 56 : 57 0 : bool BuildInfo::get_embedded() const 58 : { 59 0 : return m_embedded; 60 : } 61 : 62 0 : void BuildInfo::set_public_version(const std::string &version) 63 : { 64 0 : m_public_version = version; 65 0 : } 66 : 67 0 : const std::string &BuildInfo::get_public_version() const 68 : { 69 0 : return m_public_version; 70 : } 71 : 72 0 : void BuildInfo::set_product_version(const std::string &version) 73 : { 74 0 : m_product_version = version; 75 0 : } 76 : 77 0 : const std::string &BuildInfo::get_product_version() const 78 : { 79 0 : return m_product_version; 80 : } 81 : 82 0 : void BuildInfo::set_version4(const std::string &version4) 83 : { 84 0 : m_version4 = version4; 85 0 : } 86 : 87 0 : const std::string &BuildInfo::get_version4() const 88 : { 89 0 : return m_version4; 90 : } 91 : 92 0 : void BuildInfo::set_build_id(const std::string &build_id) 93 : { 94 0 : m_build_id = build_id; 95 0 : } 96 : 97 0 : const std::string &BuildInfo::get_build_id() const 98 : { 99 0 : return m_build_id; 100 : } 101 : 102 0 : void BuildInfo::set_git_sha(const std::string &sha) 103 : { 104 0 : m_git_sha = sha; 105 0 : } 106 : 107 0 : const std::string &BuildInfo::get_git_sha() const 108 : { 109 0 : return m_git_sha; 110 : } 111 : 112 0 : void BuildInfo::set_git_short_sha(const std::string &sha) 113 : { 114 0 : m_git_short_sha = sha; 115 0 : } 116 : 117 0 : const std::string &BuildInfo::get_git_short_sha() const 118 : { 119 0 : return m_git_short_sha; 120 : } 121 : 122 0 : void BuildInfo::set_git_ref(const std::string &ref) 123 : { 124 0 : m_git_ref = ref; 125 0 : } 126 : 127 0 : const std::string &BuildInfo::get_git_ref() const 128 : { 129 0 : return m_git_ref; 130 : } 131 : 132 0 : void BuildInfo::set_git_tag(const std::string &tag) 133 : { 134 0 : m_git_tag = tag; 135 0 : } 136 : 137 0 : const std::string &BuildInfo::get_git_tag() const 138 : { 139 0 : return m_git_tag; 140 : } 141 : 142 0 : void BuildInfo::set_pipeline_id(const std::string &id) 143 : { 144 0 : m_pipeline_id = id; 145 0 : } 146 : 147 0 : const std::string &BuildInfo::get_pipeline_id() const 148 : { 149 0 : return m_pipeline_id; 150 : } 151 : 152 0 : void BuildInfo::set_pipeline_iid(const std::string &iid) 153 : { 154 0 : m_pipeline_iid = iid; 155 0 : } 156 : 157 0 : const std::string &BuildInfo::get_pipeline_iid() const 158 : { 159 0 : return m_pipeline_iid; 160 : } 161 : 162 0 : void BuildInfo::set_job_id(const std::string &id) 163 : { 164 0 : m_job_id = id; 165 0 : } 166 : 167 0 : const std::string &BuildInfo::get_job_id() const 168 : { 169 0 : return m_job_id; 170 : } 171 : 172 0 : void BuildInfo::set_build_date_utc(const std::string &date) 173 : { 174 0 : m_build_date_utc = date; 175 0 : } 176 : 177 0 : const std::string &BuildInfo::get_build_date_utc() const 178 : { 179 0 : return m_build_date_utc; 180 : } 181 : 182 0 : void BuildInfo::set_tagged(bool tagged) 183 : { 184 0 : m_tagged = tagged; 185 0 : } 186 : 187 0 : bool BuildInfo::get_tagged() const 188 : { 189 0 : return m_tagged; 190 : } 191 : 192 0 : void BuildInfo::add_dependency(const std::string &path, const std::string &name, const std::string &sha, 193 : const std::string &short_sha, const std::string &describe, bool present) 194 : { 195 0 : BuildDependency dep; 196 0 : dep.path = path; 197 0 : dep.name = name; 198 0 : dep.sha = sha; 199 0 : dep.short_sha = short_sha; 200 0 : dep.describe = describe; 201 0 : dep.present = present; 202 0 : m_dependencies.push_back(dep); 203 0 : } 204 : 205 0 : const std::vector<BuildDependency> &BuildInfo::get_dependencies() const 206 : { 207 0 : return m_dependencies; 208 : } 209 : 210 0 : std::string BuildInfo::format_report() const 211 : { 212 0 : std::ostringstream oss; 213 0 : constexpr int label_w = 16; 214 : 215 0 : auto line = [&](const char *label, const std::string &value) { 216 0 : oss << std::setw(label_w) << std::left << label << value << '\n'; 217 0 : }; 218 : 219 0 : if (!m_embedded) 220 : { 221 0 : oss << "Build provenance was not embedded in this binary.\n"; 222 0 : oss << "Static-exe / CI builds populate this via generate_static_exe_build_info.py.\n"; 223 0 : return oss.str(); 224 : } 225 : 226 0 : line("version", m_public_version); 227 0 : line("product", m_product_version); 228 0 : line("build-id", m_build_id); 229 0 : line("tagged", m_tagged ? "yes" : "no"); 230 0 : line("git-sha", m_git_sha); 231 0 : line("git-short", m_git_short_sha); 232 0 : line("git-ref", m_git_ref); 233 0 : line("git-tag", m_git_tag.empty() ? "-" : m_git_tag); 234 0 : line("pipeline-id", m_pipeline_id); 235 0 : line("pipeline-iid", m_pipeline_iid); 236 0 : line("job-id", m_job_id); 237 0 : line("built-utc", m_build_date_utc); 238 0 : oss << '\n'; 239 0 : oss << "dependencies (from scripts/ci/static-exe.manifest.xml):\n"; 240 0 : for (const auto &dep : m_dependencies) 241 : { 242 0 : oss << " " << std::setw(28) << std::left << dep.path; 243 0 : if (dep.present) 244 : { 245 0 : oss << dep.short_sha; 246 0 : if (!dep.describe.empty() && dep.describe != dep.short_sha) 247 0 : oss << " (" << dep.describe << ")"; 248 : } 249 : else 250 : { 251 0 : oss << "missing"; 252 : } 253 0 : if (!dep.name.empty()) 254 0 : oss << " [" << dep.name << "]"; 255 0 : oss << '\n'; 256 : } 257 0 : return oss.str(); 258 0 : } 259 : 260 : } // namespace esys::repo