diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 4bdd210..3cb8e88 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -20,13 +20,16 @@ add_library(lubuntuci SHARED common.cpp utilities.cpp) target_include_directories(lubuntuci PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(lubuntuci PUBLIC yaml-cpp::yaml-cpp PRIVATE CURL::libcurl /srv/lubuntu-ci/repos/ci-tools/lib/liblaunchpad.so) +add_library(update_maintainer_lib STATIC update-maintainer-lib.cpp) +target_include_directories(update_maintainer_lib PRIVATE /srv/lubuntu-ci/repos/ci-tools/include/launchpadlib-cpp) +target_link_libraries(update_maintainer_lib PRIVATE lubuntuci yaml-cpp::yaml-cpp CURL::libcurl) + add_executable(update-maintainer update-maintainer.cpp) -target_include_directories(update-maintainer PRIVATE /srv/lubuntu-ci/repos/ci-tools/include/launchpadlib-cpp) -target_link_libraries(update-maintainer PRIVATE lubuntuci yaml-cpp::yaml-cpp CURL::libcurl) +target_link_libraries(update-maintainer PRIVATE update_maintainer_lib) add_executable(build-packages build-packages.cpp) target_include_directories(build-packages PRIVATE /srv/lubuntu-ci/repos/ci-tools/include/launchpadlib-cpp) -target_link_libraries(build-packages PRIVATE lubuntuci PkgConfig::LIBGIT2 yaml-cpp::yaml-cpp) +target_link_libraries(build-packages PRIVATE lubuntuci PkgConfig::LIBGIT2 update_maintainer_lib yaml-cpp::yaml-cpp) add_executable(fetch-indexes fetch-indexes.cpp utilities.cpp) target_include_directories(fetch-indexes PRIVATE /srv/lubuntu-ci/repos/ci-tools/include/launchpadlib-cpp) diff --git a/cpp/build-packages.cpp b/cpp/build-packages.cpp index d3d0de6..75e9dcb 100644 --- a/cpp/build-packages.cpp +++ b/cpp/build-packages.cpp @@ -14,7 +14,7 @@ // along with this program. If not, see . #include "common.h" -#include "update-maintainer.h" +#include "update-maintainer-lib.h" #include #include #include diff --git a/cpp/update-maintainer-lib.cpp b/cpp/update-maintainer-lib.cpp new file mode 100644 index 0000000..a8e7fe2 --- /dev/null +++ b/cpp/update-maintainer-lib.cpp @@ -0,0 +1,215 @@ +// Copyright (C) 2024 Simon Quigley +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "update-maintainer-lib.h" +#include "update-maintainer.h" +#include +#include +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +// Definitions from update-maintainer.cpp moved here +static const char* PREVIOUS_UBUNTU_MAINTAINERS[] = { + "ubuntu core developers ", + "ubuntu core developers ", + "ubuntu motu developers " +}; +static const char* UBUNTU_MAINTAINER = "Ubuntu Developers "; + +class MaintainerUpdateException : public std::runtime_error { +public: + using std::runtime_error::runtime_error; +}; + +static std::optional find_control_file(const fs::path &debian_dir) { + fs::path control_in = debian_dir / "control.in"; + fs::path control = debian_dir / "control"; + if (fs::exists(control_in)) return control_in; + if (fs::exists(control)) return control; + return std::nullopt; +} + +static fs::path find_changelog_file(const fs::path &debian_dir) { + fs::path changelog = debian_dir / "changelog"; + if (!fs::exists(changelog)) { + throw MaintainerUpdateException("No changelog file found"); + } + return changelog; +} + +static bool xsbc_managed_by_rules(const fs::path &debian_dir) { + fs::path rules = debian_dir / "rules"; + if (!fs::exists(rules)) return false; + std::ifstream rf(rules); + std::string line; + while (std::getline(rf, line)) { + if (line.find("XSBC-Original-") != std::string::npos) { + return true; + } + } + return false; +} + +static std::string get_distribution(const fs::path &changelog_file) { + // parse first line of changelog: "package (version) dist; urgency=..." + // dist is the token after ')' + std::ifstream f(changelog_file); + if(!f) throw MaintainerUpdateException("Unable to open changelog."); + std::string first_line; + std::getline(f, first_line); + size_t pos = first_line.find(')'); + if(pos == std::string::npos) throw MaintainerUpdateException("Invalid changelog format"); + pos++; + while(pos < first_line.size() && std::isspace((unsigned char)first_line[pos])) pos++; + size_t start = pos; + while(pos < first_line.size() && !std::isspace((unsigned char)first_line[pos]) && first_line[pos] != ';') pos++; + std::string dist = first_line.substr(start, pos - start); + size_t dashpos = dist.find('-'); + if (dashpos != std::string::npos) { + dist = dist.substr(0, dashpos); + } + return dist; +} + +static std::string read_file(const fs::path &p) { + std::ifstream f(p); + if(!f) throw MaintainerUpdateException("Cannot read file: " + p.string()); + std::stringstream ss; + ss << f.rdbuf(); + return ss.str(); +} + +static void write_file(const fs::path &p, const std::string &content) { + std::ofstream f(p); + if(!f) throw MaintainerUpdateException("Cannot write file: " + p.string()); + f << content; +} + +static std::optional get_field(const std::string &content, const std::string &field_regex) { + std::regex r(field_regex, std::regex_constants::multiline); + std::smatch m; + if(std::regex_search(content, m, r)) { + return m[1].str(); + } + return std::nullopt; +} + +static std::string set_field(const std::string &content, const std::string &field_regex, const std::string &new_line) { + std::regex r(field_regex, std::regex_constants::multiline); + return std::regex_replace(content, r, new_line); +} + +static void update_maintainer_file(const fs::path &control_file, const std::string &distribution, bool verbose) { + std::string c = read_file(control_file); + + auto original_maintainer = get_field(c, "^Maintainer:\\s?(.*)$"); + if(!original_maintainer) { + throw MaintainerUpdateException("No Maintainer field found"); + } + + std::string om = *original_maintainer; + std::string om_lower = om; + for (auto &ch : om_lower) ch = (char)std::tolower((unsigned char)ch); + + // Check previous ubuntu maintainers + for (auto &pm : PREVIOUS_UBUNTU_MAINTAINERS) { + std::string pm_lower = pm; + for (auto &ch: pm_lower) ch=(char)std::tolower((unsigned char)ch); + if(pm_lower == om_lower) { + if(verbose) { + std::cout<<"The old maintainer was: "<", lower_om.size()-11) != std::string::npos) { + if(verbose) { + std::cout<<"The Maintainer email is ubuntu.com address. Doing nothing.\n"; + } + return; + } + } + + // Debian distributions: stable, testing, unstable, experimental + if(distribution=="stable"||distribution=="testing"||distribution=="unstable"||distribution=="experimental") { + if(verbose) { + std::cout<<"The package targets Debian. Doing nothing.\n"; + } + return; + } + + // set XSBC-Original-Maintainer if needed + auto orig_field = get_field(c, "^(?:[XSBC]*-)?Original-Maintainer:\\s?(.*)$"); + if(orig_field && verbose) { + std::cout<<"Overwriting original maintainer: "<< *orig_field <<"\n"; + } + + if(verbose) { + std::cout<<"The original maintainer is: "<< om <<"\n"; + std::cout<<"Resetting as: "< +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#pragma once +#include + +void update_maintainer(const std::string &debian_directory, bool verbose = false); diff --git a/cpp/update-maintainer.cpp b/cpp/update-maintainer.cpp index db8191e..b7aa275 100644 --- a/cpp/update-maintainer.cpp +++ b/cpp/update-maintainer.cpp @@ -13,206 +13,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include "update-maintainer.h" -#include -#include +#include "update-maintainer-lib.h" #include -#include -#include -#include -#include -namespace fs = std::filesystem; - -static const char* PREVIOUS_UBUNTU_MAINTAINERS[] = { - "ubuntu core developers ", - "ubuntu core developers ", - "ubuntu motu developers " -}; -static const char* UBUNTU_MAINTAINER = "Ubuntu Developers "; - -class MaintainerUpdateException : public std::runtime_error { -public: - using std::runtime_error::runtime_error; -}; - -static std::optional find_control_file(const fs::path &debian_dir) { - fs::path control_in = debian_dir / "control.in"; - fs::path control = debian_dir / "control"; - if (fs::exists(control_in)) return control_in; - if (fs::exists(control)) return control; - return std::nullopt; -} - -static fs::path find_changelog_file(const fs::path &debian_dir) { - fs::path changelog = debian_dir / "changelog"; - if (!fs::exists(changelog)) { - throw MaintainerUpdateException("No changelog file found"); - } - return changelog; -} - -static bool xsbc_managed_by_rules(const fs::path &debian_dir) { - fs::path rules = debian_dir / "rules"; - if (!fs::exists(rules)) return false; - std::ifstream rf(rules); - std::string line; - while (std::getline(rf, line)) { - if (line.find("XSBC-Original-") != std::string::npos) { - return true; - } - } - return false; -} - -static std::string get_distribution(const fs::path &changelog_file) { - // parse first line of changelog: "package (version) dist; urgency=..." - // dist is the token after ')' - std::ifstream f(changelog_file); - if(!f) throw MaintainerUpdateException("Unable to open changelog."); - std::string first_line; - std::getline(f, first_line); - size_t pos = first_line.find(')'); - if(pos == std::string::npos) throw MaintainerUpdateException("Invalid changelog format"); - pos++; - while(pos < first_line.size() && std::isspace((unsigned char)first_line[pos])) pos++; - size_t start = pos; - while(pos < first_line.size() && !std::isspace((unsigned char)first_line[pos]) && first_line[pos] != ';') pos++; - std::string dist = first_line.substr(start, pos - start); - size_t dashpos = dist.find('-'); - if (dashpos != std::string::npos) { - dist = dist.substr(0, dashpos); - } - return dist; -} - -static std::string read_file(const fs::path &p) { - std::ifstream f(p); - if(!f) throw MaintainerUpdateException("Cannot read file: " + p.string()); - std::stringstream ss; - ss << f.rdbuf(); - return ss.str(); -} - -static void write_file(const fs::path &p, const std::string &content) { - std::ofstream f(p); - if(!f) throw MaintainerUpdateException("Cannot write file: " + p.string()); - f << content; -} - -static std::optional get_field(const std::string &content, const std::string &field_regex) { - std::regex r(field_regex, std::regex_constants::multiline); - std::smatch m; - if(std::regex_search(content, m, r)) { - return m[1].str(); - } - return std::nullopt; -} - -static std::string set_field(const std::string &content, const std::string &field_regex, const std::string &new_line) { - std::regex r(field_regex, std::regex_constants::multiline); - return std::regex_replace(content, r, new_line); -} - -static void update_maintainer_file(const fs::path &control_file, const std::string &distribution, bool verbose) { - std::string c = read_file(control_file); - - auto original_maintainer = get_field(c, "^Maintainer:\\s?(.*)$"); - if(!original_maintainer) { - throw MaintainerUpdateException("No Maintainer field found"); - } - - std::string om = *original_maintainer; - std::string om_lower = om; - for (auto &ch : om_lower) ch = (char)std::tolower((unsigned char)ch); - - // Check previous ubuntu maintainers - for (auto &pm : PREVIOUS_UBUNTU_MAINTAINERS) { - std::string pm_lower = pm; - for (auto &ch: pm_lower) ch=(char)std::tolower((unsigned char)ch); - if(pm_lower == om_lower) { - if(verbose) { - std::cout<<"The old maintainer was: "<", lower_om.size()-11) != std::string::npos) { - if(verbose) { - std::cout<<"The Maintainer email is ubuntu.com address. Doing nothing.\n"; - } - return; - } - } - - // Debian distributions: stable, testing, unstable, experimental - if(distribution=="stable"||distribution=="testing"||distribution=="unstable"||distribution=="experimental") { - if(verbose) { - std::cout<<"The package targets Debian. Doing nothing.\n"; - } - return; - } - - // set XSBC-Original-Maintainer if needed - auto orig_field = get_field(c, "^(?:[XSBC]*-)?Original-Maintainer:\\s?(.*)$"); - if(orig_field && verbose) { - std::cout<<"Overwriting original maintainer: "<< *orig_field <<"\n"; - } - - if(verbose) { - std::cout<<"The original maintainer is: "<< om <<"\n"; - std::cout<<"Resetting as: "< [--verbose]" << std::endl; return 1; @@ -232,7 +36,7 @@ int main(int argc, char** argv) { if(verbose) { std::cout << "Maintainer updated successfully." << std::endl; } - } catch(const MaintainerUpdateException& e) { + } catch(const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; return 1; }