|
|
|
@ -57,103 +57,134 @@ static const std::string REAL_LINTIAN_DIR = BASE_OUTPUT_DIR + "/lintian";
|
|
|
|
|
static std::string urgency_level_override = "low";
|
|
|
|
|
static int worker_count = 5;
|
|
|
|
|
|
|
|
|
|
// Global verbosity flag
|
|
|
|
|
static bool verbose = false;
|
|
|
|
|
|
|
|
|
|
static std::ofstream log_file_stream;
|
|
|
|
|
|
|
|
|
|
static void log_all(const std::string &msg, bool is_error=false) {
|
|
|
|
|
// Helper function to get current UTC time in YYYY-MM-DDTHH:MM:SS format
|
|
|
|
|
static std::string get_current_utc_time() {
|
|
|
|
|
auto now = std::time(nullptr);
|
|
|
|
|
std::tm tm_utc;
|
|
|
|
|
gmtime_r(&now, &tm_utc);
|
|
|
|
|
char buf[20];
|
|
|
|
|
std::strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tm_utc);
|
|
|
|
|
return std::string(buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Logging functions
|
|
|
|
|
static void log_all(const std::string &level, const std::string &msg, bool is_error=false) {
|
|
|
|
|
std::string timestamp = get_current_utc_time();
|
|
|
|
|
std::string full_msg = "[" + timestamp + "] [" + level + "] " + msg + "\n";
|
|
|
|
|
|
|
|
|
|
if (is_error) {
|
|
|
|
|
std::cerr << msg;
|
|
|
|
|
} else {
|
|
|
|
|
std::cout << msg;
|
|
|
|
|
std::cerr << full_msg;
|
|
|
|
|
} else if (level != "VERBOSE") {
|
|
|
|
|
std::cout << full_msg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (log_file_stream.is_open()) {
|
|
|
|
|
log_file_stream << msg;
|
|
|
|
|
log_file_stream << full_msg;
|
|
|
|
|
log_file_stream.flush();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void log_info(const std::string &msg) {
|
|
|
|
|
log_all("[INFO] " + msg + "\n");
|
|
|
|
|
log_all("INFO", msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void log_warning(const std::string &msg) {
|
|
|
|
|
log_all("[WARN] " + msg + "\n", false);
|
|
|
|
|
log_all("WARN", msg, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void log_error(const std::string &msg) {
|
|
|
|
|
log_all("[ERROR] " + msg + "\n", true);
|
|
|
|
|
log_all("ERROR", msg, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// New function for verbose logging
|
|
|
|
|
static void log_verbose(const std::string &msg) {
|
|
|
|
|
if (verbose) {
|
|
|
|
|
log_all("VERBOSE", msg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void print_help(const std::string &prog_name) {
|
|
|
|
|
std::cout << "Usage: " << prog_name << " [OPTIONS] <config_path>\n"
|
|
|
|
|
<< "Options:\n"
|
|
|
|
|
<< " --skip-dput Skip uploading changes with dput.\n"
|
|
|
|
|
<< " --skip-cleanup Skip cleaning up the output directory after execution.\n"
|
|
|
|
|
<< " --urgency-level=LEVEL Set the urgency level (default: low).\n"
|
|
|
|
|
<< " --workers=N Set the number of worker threads (default: 5).\n"
|
|
|
|
|
<< " --verbose, -v Enable verbose logging.\n"
|
|
|
|
|
<< " --help, -h Display this help message.\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void run_command_silent_on_success(const std::vector<std::string> &cmd, const std::optional<fs::path> &cwd = std::nullopt) {
|
|
|
|
|
log_info("run_command_silent_on_success called with command: " + std::accumulate(cmd.begin(), cmd.end(), std::string(),
|
|
|
|
|
[](const std::string &a, const std::string &b) -> std::string { return a + (a.length() > 0 ? " " : "") + b; }));
|
|
|
|
|
std::string command_str = std::accumulate(cmd.begin(), cmd.end(), std::string(),
|
|
|
|
|
[](const std::string &a, const std::string &b) -> std::string { return a + (a.empty() ? "" : " ") + b; });
|
|
|
|
|
|
|
|
|
|
log_info("Running command: " + command_str);
|
|
|
|
|
if(cwd) {
|
|
|
|
|
log_info("Current working directory for command: " + cwd->string());
|
|
|
|
|
} else {
|
|
|
|
|
log_info("No specific working directory for command.");
|
|
|
|
|
log_info("Executing in directory: " + cwd->string());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string full_cmd;
|
|
|
|
|
for (auto &c: cmd) full_cmd += c + " ";
|
|
|
|
|
std::string exec_cmd = full_cmd;
|
|
|
|
|
std::string exec_cmd = command_str;
|
|
|
|
|
if(cwd) exec_cmd = "cd " + cwd->string() + " && " + exec_cmd;
|
|
|
|
|
|
|
|
|
|
log_info("Executing command: " + exec_cmd);
|
|
|
|
|
|
|
|
|
|
FILE* pipe = popen(exec_cmd.c_str(), "r");
|
|
|
|
|
if(!pipe) {
|
|
|
|
|
log_error("Failed to run command: " + full_cmd);
|
|
|
|
|
log_error("Failed to run command: " + command_str);
|
|
|
|
|
throw std::runtime_error("Command failed to start");
|
|
|
|
|
}
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
{
|
|
|
|
|
char buffer[256];
|
|
|
|
|
while(fgets(buffer,256,pipe)) {
|
|
|
|
|
while(fgets(buffer, sizeof(buffer), pipe)) {
|
|
|
|
|
ss << buffer;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
int ret = pclose(pipe);
|
|
|
|
|
log_info("Command executed with return code: " + std::to_string(ret));
|
|
|
|
|
if (ret != 0) {
|
|
|
|
|
log_error("Command failed: " + full_cmd);
|
|
|
|
|
log_error("Command failed with code " + std::to_string(ret) + ": " + command_str);
|
|
|
|
|
log_error("Output:\n" + ss.str());
|
|
|
|
|
throw std::runtime_error("Command execution failed");
|
|
|
|
|
} else {
|
|
|
|
|
log_info("Command succeeded: " + full_cmd);
|
|
|
|
|
log_verbose("Command executed successfully: " + command_str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize libgit2 once
|
|
|
|
|
static void git_init_once() {
|
|
|
|
|
log_info("git_init_once called");
|
|
|
|
|
static std::once_flag flag;
|
|
|
|
|
std::call_once(flag, [](){
|
|
|
|
|
log_info("Initializing libgit2");
|
|
|
|
|
git_libgit2_init();
|
|
|
|
|
log_info("libgit2 initialized");
|
|
|
|
|
log_verbose("libgit2 initialized");
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void git_fetch_and_checkout(const fs::path &repo_path, const std::string &repo_url, const std::optional<std::string> &branch) {
|
|
|
|
|
log_info("git_fetch_and_checkout called with repo_path: " + repo_path.string() + ", repo_url: " + repo_url + ", branch: " + (branch ? *branch : "none"));
|
|
|
|
|
log_info("Fetching and checking out repository: " + repo_url + " into " + repo_path.string());
|
|
|
|
|
git_init_once();
|
|
|
|
|
git_repository* repo = nullptr;
|
|
|
|
|
bool need_clone = false;
|
|
|
|
|
|
|
|
|
|
if(fs::exists(repo_path)) {
|
|
|
|
|
log_info("Repository path exists. Attempting to open repository.");
|
|
|
|
|
log_verbose("Repository path exists. Attempting to open repository.");
|
|
|
|
|
int err = git_repository_open(&repo, repo_path.string().c_str());
|
|
|
|
|
if(err < 0) {
|
|
|
|
|
log_warning("Cannot open repo at " + repo_path.string() + ", recloning");
|
|
|
|
|
log_warning("Cannot open repo at " + repo_path.string() + ", recloning.");
|
|
|
|
|
fs::remove_all(repo_path);
|
|
|
|
|
need_clone = true;
|
|
|
|
|
} else {
|
|
|
|
|
log_info("Repository opened successfully.");
|
|
|
|
|
log_verbose("Repository opened successfully.");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log_info("Repository path does not exist. Cloning required.");
|
|
|
|
|
log_verbose("Repository path does not exist. Cloning required.");
|
|
|
|
|
need_clone = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!need_clone && repo != nullptr) {
|
|
|
|
|
log_info("Checking remote 'origin' for repository.");
|
|
|
|
|
git_remote* remote = nullptr;
|
|
|
|
|
int err = git_remote_lookup(&remote, repo, "origin");
|
|
|
|
|
if(err < 0) {
|
|
|
|
@ -164,24 +195,23 @@ static void git_fetch_and_checkout(const fs::path &repo_path, const std::string
|
|
|
|
|
} else {
|
|
|
|
|
const char* url = git_remote_url(remote);
|
|
|
|
|
if(!url || repo_url != url) {
|
|
|
|
|
log_info("Remote URL differs (current: " + std::string(url ? url : "null") + "). Removing and recloning.");
|
|
|
|
|
log_warning("Remote URL differs (current: " + std::string(url ? url : "null") + "). Recloning.");
|
|
|
|
|
git_remote_free(remote);
|
|
|
|
|
git_repository_free(repo);
|
|
|
|
|
fs::remove_all(repo_path);
|
|
|
|
|
need_clone = true;
|
|
|
|
|
} else {
|
|
|
|
|
log_info("Remote URL matches. Proceeding to fetch.");
|
|
|
|
|
// fetch
|
|
|
|
|
log_verbose("Remote URL matches. Fetching latest changes.");
|
|
|
|
|
// Fetch
|
|
|
|
|
git_remote_free(remote);
|
|
|
|
|
git_remote* origin = nullptr;
|
|
|
|
|
git_remote_lookup(&origin, repo, "origin");
|
|
|
|
|
git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
|
|
|
|
|
git_remote_fetch(origin, nullptr, &fetch_opts, nullptr);
|
|
|
|
|
log_info("Fetch completed.");
|
|
|
|
|
git_remote_free(origin);
|
|
|
|
|
log_verbose("Fetch completed.");
|
|
|
|
|
|
|
|
|
|
if(branch) {
|
|
|
|
|
log_info("Checking out branch: " + *branch);
|
|
|
|
|
git_reference* ref = nullptr;
|
|
|
|
|
std::string fullbranch = "refs/remotes/origin/" + *branch;
|
|
|
|
|
if(git_reference_lookup(&ref, repo, fullbranch.c_str()) == 0) {
|
|
|
|
@ -195,7 +225,7 @@ static void git_fetch_and_checkout(const fs::path &repo_path, const std::string
|
|
|
|
|
git_object_free(target);
|
|
|
|
|
log_info("Checked out branch: " + *branch);
|
|
|
|
|
} else {
|
|
|
|
|
log_error("Branch " + *branch + " not found, recloning");
|
|
|
|
|
log_warning("Branch " + *branch + " not found, recloning.");
|
|
|
|
|
git_repository_free(repo);
|
|
|
|
|
fs::remove_all(repo_path);
|
|
|
|
|
need_clone = true;
|
|
|
|
@ -222,7 +252,6 @@ static void git_fetch_and_checkout(const fs::path &repo_path, const std::string
|
|
|
|
|
log_info("Repository cloned successfully.");
|
|
|
|
|
|
|
|
|
|
if(branch) {
|
|
|
|
|
log_info("Checking out branch after clone: " + *branch);
|
|
|
|
|
git_reference* ref = nullptr;
|
|
|
|
|
std::string fullbranch = "refs/remotes/origin/" + *branch;
|
|
|
|
|
if(git_reference_lookup(&ref, newrepo, fullbranch.c_str()) == 0) {
|
|
|
|
@ -236,14 +265,14 @@ static void git_fetch_and_checkout(const fs::path &repo_path, const std::string
|
|
|
|
|
git_object_free(target);
|
|
|
|
|
log_info("Checked out branch: " + *branch + " after clone.");
|
|
|
|
|
} else {
|
|
|
|
|
log_error("Git checkout of branch " + *branch + " failed after clone.");
|
|
|
|
|
log_warning("Git checkout of branch " + *branch + " failed after clone.");
|
|
|
|
|
git_repository_free(newrepo);
|
|
|
|
|
throw std::runtime_error("Branch checkout failed");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
git_repository_free(newrepo);
|
|
|
|
|
}
|
|
|
|
|
log_info("git_fetch_and_checkout completed for " + repo_path.string());
|
|
|
|
|
log_verbose("Finished fetching and checking out repository: " + repo_path.string());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static YAML::Node load_config(const fs::path &config_path) {
|
|
|
|
@ -253,14 +282,13 @@ static YAML::Node load_config(const fs::path &config_path) {
|
|
|
|
|
log_error("Config file missing 'packages' or 'releases' sections.");
|
|
|
|
|
throw std::runtime_error("Config file must contain 'packages' and 'releases' sections.");
|
|
|
|
|
}
|
|
|
|
|
log_info("Configuration loaded successfully.");
|
|
|
|
|
log_verbose("Configuration loaded successfully.");
|
|
|
|
|
return config;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void publish_lintian() {
|
|
|
|
|
log_info("publish_lintian called.");
|
|
|
|
|
log_info("Publishing Lintian results.");
|
|
|
|
|
if(!BASE_LINTIAN_DIR.empty() && fs::exists(BASE_LINTIAN_DIR)) {
|
|
|
|
|
log_info("Publishing lintian results from " + BASE_LINTIAN_DIR);
|
|
|
|
|
for (auto &p : fs::recursive_directory_iterator(BASE_LINTIAN_DIR)) {
|
|
|
|
|
if (fs::is_regular_file(p)) {
|
|
|
|
|
fs::path rel = fs::relative(p.path(), BASE_LINTIAN_DIR);
|
|
|
|
@ -269,25 +297,26 @@ static void publish_lintian() {
|
|
|
|
|
std::error_code ec;
|
|
|
|
|
fs::copy_file(p.path(), dest, fs::copy_options::overwrite_existing, ec);
|
|
|
|
|
if(ec) {
|
|
|
|
|
log_error("Failed to copy lintian file: " + p.path().string() + " to " + dest.string() + ". Error: " + ec.message());
|
|
|
|
|
log_error("Failed to copy Lintian file: " + p.path().string() + " to " + dest.string() + ". Error: " + ec.message());
|
|
|
|
|
} else {
|
|
|
|
|
log_info("Copied lintian file: " + p.path().string() + " to " + dest.string());
|
|
|
|
|
log_verbose("Copied Lintian file: " + p.path().string() + " to " + dest.string());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fs::remove_all(BASE_LINTIAN_DIR);
|
|
|
|
|
log_info("Removed temporary lintian directory: " + BASE_LINTIAN_DIR);
|
|
|
|
|
log_info("Removed temporary Lintian directory: " + BASE_LINTIAN_DIR);
|
|
|
|
|
} else {
|
|
|
|
|
log_info("No lintian directory to publish.");
|
|
|
|
|
log_verbose("No Lintian directory to publish.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Define get_exclusions here before usage
|
|
|
|
|
static std::vector<std::string> get_exclusions(const fs::path &packaging) {
|
|
|
|
|
log_info("get_exclusions called for packaging directory: " + packaging.string());
|
|
|
|
|
log_verbose("Retrieving exclusions from: " + packaging.string());
|
|
|
|
|
std::vector<std::string> exclusions;
|
|
|
|
|
fs::path cpr = packaging / "debian" / "copyright";
|
|
|
|
|
if(!fs::exists(cpr)) {
|
|
|
|
|
log_info("No copyright file found at " + cpr.string());
|
|
|
|
|
log_verbose("No copyright file found at " + cpr.string());
|
|
|
|
|
return exclusions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -300,7 +329,7 @@ static std::vector<std::string> get_exclusions(const fs::path &packaging) {
|
|
|
|
|
bool found = false;
|
|
|
|
|
while(std::getline(f, line)) {
|
|
|
|
|
if (line.find("Files-Excluded:") != std::string::npos) {
|
|
|
|
|
log_info("Found 'Files-Excluded' in copyright.");
|
|
|
|
|
log_verbose("Found 'Files-Excluded' in copyright.");
|
|
|
|
|
size_t pos = line.find(':');
|
|
|
|
|
if(pos != std::string::npos) {
|
|
|
|
|
std::string excl = line.substr(pos + 1);
|
|
|
|
@ -308,7 +337,7 @@ static std::vector<std::string> get_exclusions(const fs::path &packaging) {
|
|
|
|
|
std::string token;
|
|
|
|
|
while(iss >> token) {
|
|
|
|
|
exclusions.push_back(token);
|
|
|
|
|
log_info("Exclusion added: " + token);
|
|
|
|
|
log_verbose("Exclusion added: " + token);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
found = true;
|
|
|
|
@ -316,12 +345,33 @@ static std::vector<std::string> get_exclusions(const fs::path &packaging) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(!found) {
|
|
|
|
|
log_info("'Files-Excluded' not found in copyright.");
|
|
|
|
|
log_verbose("'Files-Excluded' not found in copyright.");
|
|
|
|
|
}
|
|
|
|
|
return exclusions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char** argv) {
|
|
|
|
|
// Parse command-line arguments first to set verbosity
|
|
|
|
|
std::string prog_name = fs::path(argv[0]).filename().string();
|
|
|
|
|
for(int i = 1; i < argc; i++) {
|
|
|
|
|
std::string arg = argv[i];
|
|
|
|
|
if(arg == "--help" || arg == "-h") {
|
|
|
|
|
print_help(prog_name);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if(arg == "--verbose" || arg == "-v") {
|
|
|
|
|
verbose = true;
|
|
|
|
|
// Remove the verbose flag from argc and argv for further processing
|
|
|
|
|
// Shift the arguments left
|
|
|
|
|
for(int j = i; j < argc - 1; j++) {
|
|
|
|
|
argv[j] = argv[j+1];
|
|
|
|
|
}
|
|
|
|
|
argc--;
|
|
|
|
|
i--;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log_info("Script started.");
|
|
|
|
|
fs::create_directories(LOG_DIR);
|
|
|
|
|
log_info("Ensured log directory exists: " + LOG_DIR);
|
|
|
|
@ -329,15 +379,16 @@ int main(int argc, char** argv) {
|
|
|
|
|
log_info("Ensured output directory exists: " + OUTPUT_DIR);
|
|
|
|
|
|
|
|
|
|
auto now = std::time(nullptr);
|
|
|
|
|
std::tm tm = *std::gmtime(&now);
|
|
|
|
|
char buf[32];
|
|
|
|
|
std::strftime(buf, sizeof(buf), "%Y%m%dT%H%M%S", &tm);
|
|
|
|
|
std::string current_time = buf;
|
|
|
|
|
std::tm tm;
|
|
|
|
|
gmtime_r(&now, &tm);
|
|
|
|
|
char buf_time[20];
|
|
|
|
|
std::strftime(buf_time, sizeof(buf_time), "%Y-%m-%dT%H:%M:%S", &tm);
|
|
|
|
|
std::string current_time = buf_time;
|
|
|
|
|
|
|
|
|
|
std::string uuid_part = current_time.substr(0,8);
|
|
|
|
|
std::string uuid_part = current_time.substr(0,10); // Adjusted to match timestamp length
|
|
|
|
|
BASE_LINTIAN_DIR = BASE_OUTPUT_DIR + "/.lintian.tmp." + uuid_part;
|
|
|
|
|
fs::create_directories(BASE_LINTIAN_DIR);
|
|
|
|
|
log_info("Created lintian temporary directory: " + BASE_LINTIAN_DIR);
|
|
|
|
|
log_info("Created Lintian temporary directory: " + BASE_LINTIAN_DIR);
|
|
|
|
|
|
|
|
|
|
fs::path log_file = fs::path(LOG_DIR) / (current_time + ".log");
|
|
|
|
|
log_info("Opening log file: " + log_file.string());
|
|
|
|
@ -353,16 +404,16 @@ int main(int argc, char** argv) {
|
|
|
|
|
std::string config_path;
|
|
|
|
|
for(int i = 1; i < argc; i++) {
|
|
|
|
|
std::string arg = argv[i];
|
|
|
|
|
log_info("Processing command-line argument: " + arg);
|
|
|
|
|
log_info("Processing argument: " + arg);
|
|
|
|
|
if(arg == "--skip-dput") {
|
|
|
|
|
skip_dput = true;
|
|
|
|
|
log_info("Flag set to skip dput.");
|
|
|
|
|
log_info("Flag set: --skip-dput");
|
|
|
|
|
} else if(arg == "--skip-cleanup") {
|
|
|
|
|
skip_cleanup = true;
|
|
|
|
|
log_info("Flag set to skip cleanup.");
|
|
|
|
|
log_info("Flag set: --skip-cleanup");
|
|
|
|
|
} else if(arg.rfind("--urgency-level=", 0) == 0) {
|
|
|
|
|
urgency_level_override = arg.substr(std::string("--urgency-level=").size());
|
|
|
|
|
log_info("Urgency level override set to: " + urgency_level_override);
|
|
|
|
|
log_info("Urgency level overridden to: " + urgency_level_override);
|
|
|
|
|
} else if(arg.rfind("--workers=", 0) == 0) {
|
|
|
|
|
worker_count = std::stoi(arg.substr(std::string("--workers=").size()));
|
|
|
|
|
if(worker_count < 1) worker_count = 1;
|
|
|
|
@ -375,13 +426,14 @@ int main(int argc, char** argv) {
|
|
|
|
|
|
|
|
|
|
if(config_path.empty()) {
|
|
|
|
|
log_error("No config file specified.");
|
|
|
|
|
print_help(prog_name);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setenv("DEBFULLNAME", DEBFULLNAME.c_str(), 1);
|
|
|
|
|
log_info("Set environment variable DEBFULLNAME to " + DEBFULLNAME);
|
|
|
|
|
log_info("Set DEBFULLNAME to: " + DEBFULLNAME);
|
|
|
|
|
setenv("DEBEMAIL", DEBEMAIL.c_str(), 1);
|
|
|
|
|
log_info("Set environment variable DEBEMAIL to " + DEBEMAIL);
|
|
|
|
|
log_info("Set DEBEMAIL to: " + DEBEMAIL);
|
|
|
|
|
|
|
|
|
|
YAML::Node config;
|
|
|
|
|
try {
|
|
|
|
@ -399,17 +451,15 @@ int main(int argc, char** argv) {
|
|
|
|
|
log_info("Set current working directory to BASE_DIR: " + BASE_DIR);
|
|
|
|
|
|
|
|
|
|
auto get_packaging_branch = [&](const YAML::Node &pkg) -> std::optional<std::string> {
|
|
|
|
|
log_info("Determining packaging branch for package.");
|
|
|
|
|
if(pkg["packaging_branch"] && pkg["packaging_branch"].IsScalar()) {
|
|
|
|
|
std::string branch = pkg["packaging_branch"].as<std::string>();
|
|
|
|
|
log_info("Packaging branch found in package config: " + branch);
|
|
|
|
|
log_info("Packaging branch for package: " + branch);
|
|
|
|
|
return branch;
|
|
|
|
|
} else if (releases.size() > 0) {
|
|
|
|
|
std::string branch = "ubuntu/" + releases[0].as<std::string>();
|
|
|
|
|
log_info("Defaulting packaging branch to: " + branch);
|
|
|
|
|
log_info("Default packaging branch set to: " + branch);
|
|
|
|
|
return branch;
|
|
|
|
|
}
|
|
|
|
|
log_info("No packaging branch specified.");
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -429,25 +479,26 @@ int main(int argc, char** argv) {
|
|
|
|
|
throw std::runtime_error("Invalid changelog format");
|
|
|
|
|
}
|
|
|
|
|
std::string version_match = first_line.substr(start + 1, end - (start + 1));
|
|
|
|
|
log_info("Extracted version string: " + version_match);
|
|
|
|
|
log_verbose("Extracted version: " + version_match);
|
|
|
|
|
std::string epoch;
|
|
|
|
|
std::string upstream_version = version_match;
|
|
|
|
|
if(auto pos = version_match.find(':'); pos != std::string::npos) {
|
|
|
|
|
epoch = version_match.substr(0, pos);
|
|
|
|
|
upstream_version = version_match.substr(pos + 1);
|
|
|
|
|
log_info("Parsed epoch: " + epoch + ", upstream version: " + upstream_version);
|
|
|
|
|
log_verbose("Parsed epoch: " + epoch + ", upstream version: " + upstream_version);
|
|
|
|
|
}
|
|
|
|
|
if(auto pos = upstream_version.find('-'); pos != std::string::npos) {
|
|
|
|
|
upstream_version = upstream_version.substr(0, pos);
|
|
|
|
|
log_info("Trimmed upstream version to: " + upstream_version);
|
|
|
|
|
log_verbose("Trimmed upstream version: " + upstream_version);
|
|
|
|
|
}
|
|
|
|
|
std::regex git_regex("(\\+git[0-9]+)?(~[a-z]+)?$");
|
|
|
|
|
upstream_version = std::regex_replace(upstream_version, git_regex, "");
|
|
|
|
|
log_info("Upstream version after regex replacement: " + upstream_version);
|
|
|
|
|
log_verbose("Upstream version after regex: " + upstream_version);
|
|
|
|
|
auto t = std::time(nullptr);
|
|
|
|
|
std::tm tm = *std::gmtime(&t);
|
|
|
|
|
char buf_version[32];
|
|
|
|
|
std::strftime(buf_version, sizeof(buf_version), "%Y%m%d%H%M", &tm);
|
|
|
|
|
std::tm tm_utc;
|
|
|
|
|
gmtime_r(&t, &tm_utc);
|
|
|
|
|
char buf_version[20];
|
|
|
|
|
std::strftime(buf_version, sizeof(buf_version), "%Y-%m-%dT%H:%M:%S", &tm_utc);
|
|
|
|
|
std::string current_date = buf_version;
|
|
|
|
|
std::string version;
|
|
|
|
|
if(!epoch.empty()) {
|
|
|
|
@ -460,36 +511,33 @@ int main(int argc, char** argv) {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto run_source_lintian = [&](const std::string &name, const fs::path &source_path) {
|
|
|
|
|
log_info("Running Lintian for package: " + name + " with source path: " + source_path.string());
|
|
|
|
|
log_info("Running Lintian for package: " + name);
|
|
|
|
|
fs::path temp_file = fs::temp_directory_path() / ("lintian_suppress_" + name + ".txt");
|
|
|
|
|
{
|
|
|
|
|
std::ofstream of(temp_file);
|
|
|
|
|
for (auto &tag: SUPPRESSED_LINTIAN_TAGS) {
|
|
|
|
|
of << tag << "\n";
|
|
|
|
|
log_info("Suppressed Lintian tag added: " + tag);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
log_verbose("Created Lintian suppression file: " + temp_file.string());
|
|
|
|
|
std::string cmd = "lintian -EvIL +pedantic --suppress-tags-from-file " + temp_file.string() + " " + source_path.string() + " 2>&1";
|
|
|
|
|
log_info("Executing Lintian command: " + cmd);
|
|
|
|
|
FILE* pipe = popen(cmd.c_str(), "r");
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
if(pipe) {
|
|
|
|
|
char buffer[256];
|
|
|
|
|
while(fgets(buffer,256,pipe)) {
|
|
|
|
|
while(fgets(buffer, sizeof(buffer), pipe)) {
|
|
|
|
|
ss << buffer;
|
|
|
|
|
}
|
|
|
|
|
int ret = pclose(pipe);
|
|
|
|
|
log_info("Lintian command exited with code: " + std::to_string(ret));
|
|
|
|
|
fs::remove(temp_file);
|
|
|
|
|
log_info("Removed temporary lintian suppress file: " + temp_file.string());
|
|
|
|
|
log_verbose("Lintian command exited with code: " + std::to_string(ret));
|
|
|
|
|
if(ret != 0) {
|
|
|
|
|
log_error("Lintian reported issues:\n"+ss.str());
|
|
|
|
|
log_error("Lintian reported issues for " + name + ":\n" + ss.str());
|
|
|
|
|
if(!ss.str().empty()) {
|
|
|
|
|
fs::path pkgdir = fs::path(BASE_LINTIAN_DIR) / name;
|
|
|
|
|
fs::create_directories(pkgdir);
|
|
|
|
|
std::ofstream out(pkgdir / "source.txt", std::ios::app);
|
|
|
|
|
out << ss.str() << "\n";
|
|
|
|
|
log_info("Logged lintian issues to " + (pkgdir/"source.txt").string());
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if(!ss.str().empty()) {
|
|
|
|
@ -497,42 +545,37 @@ int main(int argc, char** argv) {
|
|
|
|
|
fs::create_directories(pkgdir);
|
|
|
|
|
std::ofstream out(pkgdir / "source.txt", std::ios::app);
|
|
|
|
|
out << ss.str() << "\n";
|
|
|
|
|
log_info("Logged lintian output to " + (pkgdir/"source.txt").string());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
fs::remove(temp_file);
|
|
|
|
|
log_error("Failed to run lintian for package: " + name);
|
|
|
|
|
log_error("Failed to run Lintian for package: " + name);
|
|
|
|
|
}
|
|
|
|
|
log_info("Lintian run for " + name + " is complete");
|
|
|
|
|
log_verbose("Completed Lintian run for package: " + name);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto dput_source = [&](const std::string &name, const std::string &upload_target, const std::vector<std::string> &changes_files, const std::vector<std::string> &devel_changes_files) {
|
|
|
|
|
log_info("dput_source called for package: " + name + ", upload_target: " + upload_target);
|
|
|
|
|
log_info("Uploading changes for package: " + name + " to " + upload_target);
|
|
|
|
|
if(!changes_files.empty()) {
|
|
|
|
|
std::string hr_changes;
|
|
|
|
|
for(auto &c: changes_files) {
|
|
|
|
|
hr_changes += c+" ";
|
|
|
|
|
log_info("Change file to upload: " + c);
|
|
|
|
|
}
|
|
|
|
|
log_info("Uploading " + hr_changes + "to " + upload_target + " using dput");
|
|
|
|
|
for(auto &c: changes_files) hr_changes += c + " ";
|
|
|
|
|
log_verbose("Changes files: " + hr_changes);
|
|
|
|
|
std::vector<std::string> cmd = {"dput", upload_target};
|
|
|
|
|
for(auto &c: changes_files) cmd.push_back(c);
|
|
|
|
|
try {
|
|
|
|
|
run_command_silent_on_success(cmd, OUTPUT_DIR);
|
|
|
|
|
log_info("Completed upload of changes to " + upload_target);
|
|
|
|
|
log_info("Successfully uploaded changes for package: " + name);
|
|
|
|
|
for(auto &file: devel_changes_files) {
|
|
|
|
|
if(!file.empty()) {
|
|
|
|
|
log_info("Running Lintian on devel changes file: " + file);
|
|
|
|
|
run_source_lintian(name, file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (...) {
|
|
|
|
|
log_error("Failed to upload changes for package: " + name);
|
|
|
|
|
// error logged already
|
|
|
|
|
// Errors are already logged in run_command_silent_on_success
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log_info("No changes files to upload for package: " + name);
|
|
|
|
|
log_warning("No changes files to upload for package: " + name);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -541,22 +584,17 @@ int main(int argc, char** argv) {
|
|
|
|
|
log_info("Updating changelog for " + name + " to version " + version_with_epoch + "-0ubuntu1~ppa1");
|
|
|
|
|
try {
|
|
|
|
|
run_command_silent_on_success({"git", "checkout", "debian/changelog"}, packaging_dir);
|
|
|
|
|
log_info("Checked out debian/changelog for " + name);
|
|
|
|
|
log_verbose("Checked out debian/changelog for " + name);
|
|
|
|
|
} catch (const std::exception &e) {
|
|
|
|
|
log_error("Failed to checkout debian/changelog for " + name + ": " + e.what());
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
std::vector<std::string> cmd = {
|
|
|
|
|
"dch","--distribution",release,"--package",name,"--newversion",version_with_epoch+"-0ubuntu1~ppa1","--urgency",urgency_level_override,"CI upload."
|
|
|
|
|
"dch", "--distribution", release, "--package", name, "--newversion", version_with_epoch + "-0ubuntu1~ppa1",
|
|
|
|
|
"--urgency", urgency_level_override, "CI upload."
|
|
|
|
|
};
|
|
|
|
|
log_info("Running dch command to update changelog for " + name);
|
|
|
|
|
try {
|
|
|
|
|
run_command_silent_on_success(cmd, packaging_dir);
|
|
|
|
|
log_info("Changelog updated successfully for " + name);
|
|
|
|
|
} catch (const std::exception &e) {
|
|
|
|
|
log_error("Failed to update changelog for " + name + ": " + e.what());
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
log_info("Changelog updated for " + name);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto build_package = [&](const fs::path &packaging_dir, const std::map<std::string, std::string> &env_vars, bool large) -> std::string {
|
|
|
|
@ -566,55 +604,48 @@ int main(int argc, char** argv) {
|
|
|
|
|
if(large) {
|
|
|
|
|
temp_dir = fs::path(OUTPUT_DIR) / (".tmp_" + name + "_" + env_vars.at("VERSION"));
|
|
|
|
|
fs::create_directories(temp_dir);
|
|
|
|
|
log_warning(name+" is quite large and will not fit in /tmp, building at "+temp_dir.string());
|
|
|
|
|
log_warning(name + " is large; building in " + temp_dir.string());
|
|
|
|
|
} else {
|
|
|
|
|
temp_dir = fs::temp_directory_path() / ("tmp_build_" + name + "_" + env_vars.at("VERSION"));
|
|
|
|
|
fs::create_directories(temp_dir);
|
|
|
|
|
log_info("Temporary build directory created at " + temp_dir.string());
|
|
|
|
|
log_verbose("Created temporary build directory: " + temp_dir.string());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::error_code ec;
|
|
|
|
|
fs::path temp_packaging_dir = temp_dir / name;
|
|
|
|
|
fs::create_directories(temp_packaging_dir, ec);
|
|
|
|
|
if(ec) {
|
|
|
|
|
log_error("Failed to create temporary packaging directory: " + temp_packaging_dir.string() + ". Error: " + ec.message());
|
|
|
|
|
throw std::runtime_error("Failed to create temporary packaging directory.");
|
|
|
|
|
log_error("Failed to create temporary packaging directory: " + temp_packaging_dir.string());
|
|
|
|
|
throw std::runtime_error("Temporary packaging directory creation failed");
|
|
|
|
|
}
|
|
|
|
|
log_info("Temporary packaging directory created at " + temp_packaging_dir.string());
|
|
|
|
|
log_verbose("Temporary packaging directory created at: " + temp_packaging_dir.string());
|
|
|
|
|
|
|
|
|
|
fs::copy(packaging_dir / "debian", temp_packaging_dir / "debian", fs::copy_options::recursive, ec);
|
|
|
|
|
if(ec) {
|
|
|
|
|
log_error("Failed to copy debian directory to temporary packaging directory: " + ec.message());
|
|
|
|
|
throw std::runtime_error("Failed to copy debian directory.");
|
|
|
|
|
throw std::runtime_error("Failed to copy debian directory");
|
|
|
|
|
}
|
|
|
|
|
log_info("Copied debian directory to temporary packaging directory.");
|
|
|
|
|
log_verbose("Copied debian directory to temporary packaging directory.");
|
|
|
|
|
|
|
|
|
|
std::string tarball_name = name + "_" + env_vars.at("VERSION") + ".orig.tar.gz";
|
|
|
|
|
fs::path tarball_source = fs::path(BASE_DIR) / (name + "_MAIN.orig.tar.gz");
|
|
|
|
|
fs::path tarball_dest = temp_dir / tarball_name;
|
|
|
|
|
fs::copy_file(tarball_source, tarball_dest, fs::copy_options::overwrite_existing, ec);
|
|
|
|
|
if(ec) {
|
|
|
|
|
log_error("Failed to copy tarball from " + tarball_source.string() + " to " + tarball_dest.string() + ". Error: " + ec.message());
|
|
|
|
|
throw std::runtime_error("Failed to copy tarball.");
|
|
|
|
|
log_error("Failed to copy tarball from " + tarball_source.string() + " to " + tarball_dest.string());
|
|
|
|
|
throw std::runtime_error("Failed to copy tarball");
|
|
|
|
|
}
|
|
|
|
|
log_info("Copied tarball to " + tarball_dest.string());
|
|
|
|
|
log_verbose("Copied tarball to " + tarball_dest.string());
|
|
|
|
|
|
|
|
|
|
for (auto &e: env_vars) {
|
|
|
|
|
setenv(e.first.c_str(), e.second.c_str(), 1);
|
|
|
|
|
log_info("Set environment variable: " + e.first + " = " + e.second);
|
|
|
|
|
log_verbose("Set environment variable: " + e.first + " = " + e.second);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> cmd_build = {"debuild", "--no-lintian", "-S", "-d", "-sa", "-nc"};
|
|
|
|
|
log_info("Running debuild command in " + temp_packaging_dir.string());
|
|
|
|
|
try {
|
|
|
|
|
run_command_silent_on_success(cmd_build, temp_packaging_dir);
|
|
|
|
|
run_command_silent_on_success({"git", "checkout", "debian/changelog"}, packaging_dir);
|
|
|
|
|
log_info("Completed debuild and reset changelog for " + name);
|
|
|
|
|
} catch(...) {
|
|
|
|
|
fs::remove_all(temp_dir, ec);
|
|
|
|
|
log_error("Build failed for " + name + ". Cleaned up temporary directory.");
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
log_info("Built package for " + name);
|
|
|
|
|
|
|
|
|
|
std::string pattern = name + "_" + env_vars.at("VERSION");
|
|
|
|
|
std::string changes_file;
|
|
|
|
@ -623,10 +654,8 @@ int main(int argc, char** argv) {
|
|
|
|
|
if(fname.rfind(pattern, 0) == 0) {
|
|
|
|
|
fs::path dest = fs::path(OUTPUT_DIR) / fname;
|
|
|
|
|
fs::copy_file(entry.path(), dest, fs::copy_options::overwrite_existing, ec);
|
|
|
|
|
if(ec) {
|
|
|
|
|
log_error("Failed to copy built package " + fname + " to " + OUTPUT_DIR + ". Error: " + ec.message());
|
|
|
|
|
} else {
|
|
|
|
|
log_info("Copied " + fname + " to " + OUTPUT_DIR);
|
|
|
|
|
if(!ec) {
|
|
|
|
|
log_verbose("Copied built package " + fname + " to " + OUTPUT_DIR);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -636,15 +665,14 @@ int main(int argc, char** argv) {
|
|
|
|
|
if(fname.rfind(name + "_" + env_vars.at("VERSION"), 0) == 0 && fname.ends_with("_source.changes")) {
|
|
|
|
|
changes_file = entry.path().string();
|
|
|
|
|
log_info("Found changes file: " + changes_file);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fs::remove_all(temp_dir, ec);
|
|
|
|
|
if(ec) {
|
|
|
|
|
log_warning("Failed to remove temporary directory: " + temp_dir.string() + ". Error: " + ec.message());
|
|
|
|
|
log_warning("Failed to remove temporary directory: " + temp_dir.string());
|
|
|
|
|
} else {
|
|
|
|
|
log_info("Removed temporary build directory: " + temp_dir.string());
|
|
|
|
|
log_verbose("Removed temporary build directory: " + temp_dir.string());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(changes_file.empty()) {
|
|
|
|
@ -658,18 +686,18 @@ int main(int argc, char** argv) {
|
|
|
|
|
auto process_package = [&](const YAML::Node &pkg) {
|
|
|
|
|
std::string name = pkg["name"] ? pkg["name"].as<std::string>() : "";
|
|
|
|
|
std::string upload_target = pkg["upload_target"] ? pkg["upload_target"].as<std::string>() : "ppa:lubuntu-ci/unstable-ci-proposed";
|
|
|
|
|
log_info("Processing package: " + name + " with upload target: " + upload_target);
|
|
|
|
|
if(name.empty()) {
|
|
|
|
|
log_warning("Skipping package due to missing name.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
log_info("Processing package: " + name);
|
|
|
|
|
fs::path packaging_destination = fs::path(BASE_DIR) / name;
|
|
|
|
|
fs::path changelog_path = packaging_destination / "debian" / "changelog";
|
|
|
|
|
std::string version = parse_version(changelog_path);
|
|
|
|
|
|
|
|
|
|
bool large = pkg["large"] ? pkg["large"].as<bool>() : false;
|
|
|
|
|
if(large) {
|
|
|
|
|
log_info("Package " + name + " marked as large.");
|
|
|
|
|
log_info("Package " + name + " is marked as large.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::pair<std::string, std::map<std::string, std::string>>> built_changes;
|
|
|
|
@ -679,7 +707,7 @@ int main(int argc, char** argv) {
|
|
|
|
|
if(auto pos = version.find(':'); pos != std::string::npos) {
|
|
|
|
|
epoch = version.substr(0, pos);
|
|
|
|
|
version_no_epoch = version.substr(pos + 1);
|
|
|
|
|
log_info("Package " + name + " has epoch: " + epoch);
|
|
|
|
|
log_verbose("Package " + name + " has epoch: " + epoch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(auto rel : releases) {
|
|
|
|
@ -692,13 +720,13 @@ int main(int argc, char** argv) {
|
|
|
|
|
std::error_code ec;
|
|
|
|
|
fs::copy_file(tarball_source, tarball_dest, fs::copy_options::overwrite_existing, ec);
|
|
|
|
|
if(ec) {
|
|
|
|
|
log_error("Failed to copy tarball for " + name + " to " + tarball_dest.string() + ". Error: " + ec.message());
|
|
|
|
|
log_error("Failed to copy tarball for " + name + " to " + tarball_dest.string());
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
log_info("Copied tarball to " + tarball_dest.string());
|
|
|
|
|
log_verbose("Copied tarball to " + tarball_dest.string());
|
|
|
|
|
|
|
|
|
|
std::string version_for_dch = epoch.empty() ? release_version_no_epoch : (epoch + ":" + release_version_no_epoch);
|
|
|
|
|
log_info("Version for dch: " + version_for_dch);
|
|
|
|
|
log_verbose("Version for dch: " + version_for_dch);
|
|
|
|
|
|
|
|
|
|
std::map<std::string, std::string> env_map;
|
|
|
|
|
env_map["DEBFULLNAME"] = DEBFULLNAME;
|
|
|
|
@ -711,7 +739,6 @@ int main(int argc, char** argv) {
|
|
|
|
|
std::string changes_file = build_package(packaging_destination, env_map, large);
|
|
|
|
|
if(!changes_file.empty()) {
|
|
|
|
|
built_changes.emplace_back(changes_file, env_map);
|
|
|
|
|
log_info("Recorded built changes file: " + changes_file);
|
|
|
|
|
}
|
|
|
|
|
} catch(std::exception &e) {
|
|
|
|
|
log_error("Error processing package '" + name + "' for release '" + release + "': " + std::string(e.what()));
|
|
|
|
@ -719,9 +746,9 @@ int main(int argc, char** argv) {
|
|
|
|
|
|
|
|
|
|
fs::remove(tarball_dest, ec);
|
|
|
|
|
if(ec) {
|
|
|
|
|
log_warning("Failed to remove tarball: " + tarball_dest.string() + ". Error: " + ec.message());
|
|
|
|
|
log_warning("Failed to remove tarball: " + tarball_dest.string());
|
|
|
|
|
} else {
|
|
|
|
|
log_info("Removed tarball: " + tarball_dest.string());
|
|
|
|
|
log_verbose("Removed tarball: " + tarball_dest.string());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -729,7 +756,6 @@ int main(int argc, char** argv) {
|
|
|
|
|
for(auto &bc : built_changes) {
|
|
|
|
|
fs::path cf(bc.first);
|
|
|
|
|
changes_files.push_back(cf.filename().string());
|
|
|
|
|
log_info("Collected changes file: " + cf.filename().string());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unordered_set<std::string> devel_changes_files;
|
|
|
|
@ -738,10 +764,8 @@ int main(int argc, char** argv) {
|
|
|
|
|
for(auto &f : changes_files) {
|
|
|
|
|
if(f.find("~" + first_release) != std::string::npos) {
|
|
|
|
|
devel_changes_files.insert((fs::path(OUTPUT_DIR) / f).string());
|
|
|
|
|
log_info("Added to devel changes files: " + (fs::path(OUTPUT_DIR)/f).string());
|
|
|
|
|
} else {
|
|
|
|
|
devel_changes_files.insert(std::string());
|
|
|
|
|
log_info("Added empty string to devel changes files.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -753,15 +777,15 @@ int main(int argc, char** argv) {
|
|
|
|
|
|
|
|
|
|
if(getenv("DEBFULLNAME") == nullptr) {
|
|
|
|
|
setenv("DEBFULLNAME", DEBFULLNAME.c_str(), 1);
|
|
|
|
|
log_info("Set environment variable DEBFULLNAME for package: " + name);
|
|
|
|
|
log_info("Set DEBFULLNAME environment variable.");
|
|
|
|
|
}
|
|
|
|
|
if(getenv("DEBEMAIL") == nullptr) {
|
|
|
|
|
setenv("DEBEMAIL", DEBEMAIL.c_str(), 1);
|
|
|
|
|
log_info("Set environment variable DEBEMAIL for package: " + name);
|
|
|
|
|
log_info("Set DEBEMAIL environment variable.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(skip_dput) {
|
|
|
|
|
log_info("Skipping dput for package: " + name);
|
|
|
|
|
log_info("Skipping dput upload for package: " + name);
|
|
|
|
|
for(auto &file : devel_changes_files) {
|
|
|
|
|
if(!file.empty()) {
|
|
|
|
|
run_source_lintian(name, file);
|
|
|
|
@ -769,32 +793,30 @@ int main(int argc, char** argv) {
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
std::string real_upload_target = built_changes[0].second.at("UPLOAD_TARGET");
|
|
|
|
|
log_info("Uploading changes for package: " + name + " to " + real_upload_target);
|
|
|
|
|
dput_source(name, real_upload_target, changes_files, std::vector<std::string>(devel_changes_files.begin(), devel_changes_files.end()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fs::remove(fs::path(BASE_DIR) / (name + "_MAIN.orig.tar.gz"));
|
|
|
|
|
log_info("Removed main orig tarball for package: " + name);
|
|
|
|
|
log_verbose("Removed main orig tarball for package: " + name);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto prepare_package = [&](const YAML::Node &pkg) {
|
|
|
|
|
std::string name = pkg["name"] ? pkg["name"].as<std::string>() : "";
|
|
|
|
|
log_info("Preparing package: " + name);
|
|
|
|
|
if(name.empty()) {
|
|
|
|
|
log_warning("Skipping package due to missing name.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
log_info("Preparing package: " + name);
|
|
|
|
|
|
|
|
|
|
std::string upstream_url = pkg["upstream_url"] ? pkg["upstream_url"].as<std::string>() : ("https://github.com/lxqt/" + name + ".git");
|
|
|
|
|
log_info("Upstream URL for " + name + ": " + upstream_url);
|
|
|
|
|
log_verbose("Upstream URL: " + upstream_url);
|
|
|
|
|
fs::path upstream_destination = fs::path(BASE_DIR) / ("upstream-" + name);
|
|
|
|
|
std::optional<std::string> packaging_branch = get_packaging_branch(pkg);
|
|
|
|
|
std::string packaging_url = pkg["packaging_url"] ? pkg["packaging_url"].as<std::string>() : ("https://git.lubuntu.me/Lubuntu/" + name + "-packaging.git");
|
|
|
|
|
log_info("Packaging URL for " + name + ": " + packaging_url);
|
|
|
|
|
log_verbose("Packaging URL: " + packaging_url);
|
|
|
|
|
fs::path packaging_destination = fs::path(BASE_DIR) / name;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
log_info("Fetching and checking out upstream repository for " + name);
|
|
|
|
|
git_fetch_and_checkout(upstream_destination, upstream_url, std::nullopt);
|
|
|
|
|
} catch(...) {
|
|
|
|
|
log_error("Failed to prepare upstream repo for " + name);
|
|
|
|
@ -802,7 +824,6 @@ int main(int argc, char** argv) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
log_info("Fetching and checking out packaging repository for " + name);
|
|
|
|
|
git_fetch_and_checkout(packaging_destination, packaging_url, packaging_branch);
|
|
|
|
|
} catch(...) {
|
|
|
|
|
log_error("Failed to prepare packaging repo for " + name);
|
|
|
|
@ -810,45 +831,44 @@ int main(int argc, char** argv) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
log_info("Updating maintainer scripts for " + name);
|
|
|
|
|
log_info("Updating maintainer for package: " + name);
|
|
|
|
|
update_maintainer((packaging_destination / "debian").string(), false);
|
|
|
|
|
log_info("Maintainer scripts updated for " + name);
|
|
|
|
|
log_info("Maintainer updated for package: " + name);
|
|
|
|
|
} catch(std::exception &e) {
|
|
|
|
|
log_warning("update_maintainer: "+std::string(e.what())+" for "+name);
|
|
|
|
|
log_warning("update_maintainer error for " + name + ": " + std::string(e.what()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto exclusions = get_exclusions(packaging_destination);
|
|
|
|
|
log_info("Creating tarball for " + name);
|
|
|
|
|
log_info("Creating tarball for package: " + name);
|
|
|
|
|
create_tarball(name, upstream_destination, exclusions);
|
|
|
|
|
log_info("Tarball created for " + name);
|
|
|
|
|
log_info("Tarball created for package: " + name);
|
|
|
|
|
|
|
|
|
|
process_package(pkg);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::vector<std::future<void>> futures;
|
|
|
|
|
log_info("Starting package preparation with " + std::to_string(packages.size()) + " packages.");
|
|
|
|
|
log_info("Starting package preparation for " + std::to_string(packages.size()) + " packages.");
|
|
|
|
|
for(auto pkg : packages) {
|
|
|
|
|
log_info("Submitting package to be prepared: " + (pkg["name"] ? pkg["name"].as<std::string>() : "Unnamed"));
|
|
|
|
|
futures.push_back(std::async(std::launch::async, prepare_package, pkg));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(auto &fut : futures) {
|
|
|
|
|
try {
|
|
|
|
|
fut.get();
|
|
|
|
|
log_info("Package processing completed successfully.");
|
|
|
|
|
log_info("Package processed successfully.");
|
|
|
|
|
} catch(std::exception &e) {
|
|
|
|
|
log_error(std::string("Task generated an exception: ") + e.what());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!skip_cleanup) {
|
|
|
|
|
log_info("Performing cleanup of output directory: " + OUTPUT_DIR);
|
|
|
|
|
log_info("Cleaning up output directory: " + OUTPUT_DIR);
|
|
|
|
|
fs::remove_all(OUTPUT_DIR);
|
|
|
|
|
log_info("Cleanup completed.");
|
|
|
|
|
} else {
|
|
|
|
|
log_info("Skipping cleanup as per flag.");
|
|
|
|
|
}
|
|
|
|
|
log_info("Publishing Lintian output...");
|
|
|
|
|
log_info("Publishing Lintian results.");
|
|
|
|
|
publish_lintian();
|
|
|
|
|
log_info("Cleaning old logs.");
|
|
|
|
|
clean_old_logs(fs::path(LOG_DIR));
|
|
|
|
|