Move common filesystem utilities from utilities to a new fs_common
This commit is contained in:
		
							parent
							
								
									8422093caf
								
							
						
					
					
						commit
						946235318a
					
				| @ -42,6 +42,7 @@ set(UUID_LIB "uuid") | |||||||
| add_library(lubuntuci_lib SHARED | add_library(lubuntuci_lib SHARED | ||||||
|     utilities.cpp |     utilities.cpp | ||||||
|     db_common.cpp |     db_common.cpp | ||||||
|  |     fs_common.cpp | ||||||
|     git_common.cpp |     git_common.cpp | ||||||
|     tar_common.cpp |     tar_common.cpp | ||||||
|     sources_parser.cpp |     sources_parser.cpp | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ | |||||||
| #include "ci_logic.h" | #include "ci_logic.h" | ||||||
| #include "db_common.h" | #include "db_common.h" | ||||||
| #include "git_common.h" | #include "git_common.h" | ||||||
|  | #include "fs_common.h" | ||||||
| #include "tar_common.h" | #include "tar_common.h" | ||||||
| #include "task_queue.h" | #include "task_queue.h" | ||||||
| #include "utilities.h" | #include "utilities.h" | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ | |||||||
| // You should have received a copy of the GNU General Public License
 | // You should have received a copy of the GNU General Public License
 | ||||||
| // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||||
| 
 | 
 | ||||||
|  | #include "fs_common.h" | ||||||
| #include "utilities.h" | #include "utilities.h" | ||||||
| 
 | 
 | ||||||
| #include "launchpad.h" | #include "launchpad.h" | ||||||
|  | |||||||
							
								
								
									
										100
									
								
								cpp/fs_common.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								cpp/fs_common.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | |||||||
|  | // Copyright (C) 2025 Simon Quigley <tsimonq2@ubuntu.com>
 | ||||||
|  | //
 | ||||||
|  | // 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 <https://www.gnu.org/licenses/>.
 | ||||||
|  | 
 | ||||||
|  | #include <cstring> | ||||||
|  | #include <cstdlib> | ||||||
|  | #include <fstream> | ||||||
|  | #include <iostream> | ||||||
|  | #include <filesystem> | ||||||
|  | #include <format> | ||||||
|  | #include <regex> | ||||||
|  | #include <sstream> | ||||||
|  | 
 | ||||||
|  | #include "fs_common.h" | ||||||
|  | #include "utilities.h" | ||||||
|  | 
 | ||||||
|  | namespace fs = std::filesystem; | ||||||
|  | 
 | ||||||
|  | // Function to read the entire content of a file into a string
 | ||||||
|  | std::string read_file(const fs::path& file_path) { | ||||||
|  |     std::ifstream in_file(file_path, std::ios::binary); | ||||||
|  |     if (in_file) return std::string((std::istreambuf_iterator<char>(in_file)), | ||||||
|  |                                     std::istreambuf_iterator<char>()); | ||||||
|  |     return ""; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Function to write a string into a file
 | ||||||
|  | void write_file(const fs::path& file_path, const std::string& content) { | ||||||
|  |     std::ofstream out_file(file_path, std::ios::binary); | ||||||
|  |     if (out_file) out_file << content; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Function to perform in-place regex replace on a file
 | ||||||
|  | void regex_replace_in_file(const fs::path& file_path, const std::string& pattern, const std::string& replacement) { | ||||||
|  |     std::string content = read_file(file_path); | ||||||
|  |     content = std::regex_replace(content, std::regex(pattern), replacement); | ||||||
|  |     write_file(file_path, content); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::filesystem::path create_temp_directory() { | ||||||
|  |     auto temp_dir = std::filesystem::temp_directory_path() / generate_random_string(32); | ||||||
|  |     std::filesystem::create_directory(temp_dir); | ||||||
|  |     return temp_dir; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Function to copy a directory recursively
 | ||||||
|  | void copy_directory(const fs::path& source, const fs::path& destination) { | ||||||
|  |     if (!std::filesystem::exists(source) || !std::filesystem::is_directory(source)) throw std::runtime_error("Source directory does not exist or is not a directory: " + source.string()); | ||||||
|  | 
 | ||||||
|  |     // Create the destination directory
 | ||||||
|  |     std::filesystem::create_directories(destination); | ||||||
|  | 
 | ||||||
|  |     // Copy files and directories recursively
 | ||||||
|  |     for (const auto& entry : std::filesystem::recursive_directory_iterator(source)) { | ||||||
|  |         auto relative_path = std::filesystem::relative(entry.path(), source); | ||||||
|  |         auto target_path = destination / relative_path; | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             if (std::filesystem::is_directory(entry)) std::filesystem::create_directory(target_path); | ||||||
|  |             else if (std::filesystem::is_regular_file(entry)) std::filesystem::copy(entry, target_path, std::filesystem::copy_options::overwrite_existing); | ||||||
|  |         } catch (...) { | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Function to extract excluded files from a copyright file
 | ||||||
|  | std::vector<std::string> extract_files_excluded(const std::string& filepath) { | ||||||
|  |     std::ifstream file(filepath); | ||||||
|  |     if (!file.is_open()) throw std::runtime_error("Failed to open file: " + filepath); | ||||||
|  | 
 | ||||||
|  |     std::vector<std::string> files_excluded; | ||||||
|  |     std::string line; | ||||||
|  |     std::regex files_excluded_pattern(R"(Files-Excluded:\s*(.*))"); | ||||||
|  |     bool in_files_excluded = false; | ||||||
|  | 
 | ||||||
|  |     while (std::getline(file, line)) { | ||||||
|  |         if (std::regex_match(line, files_excluded_pattern)) { | ||||||
|  |             in_files_excluded = true; | ||||||
|  |             std::smatch match; | ||||||
|  |             if (std::regex_search(line, match, files_excluded_pattern) && match.size() > 1) files_excluded.emplace_back(match[1]); | ||||||
|  |         } else if (in_files_excluded) { | ||||||
|  |             if (!line.empty() && (line[0] == ' ' || line[0] == '\t')) files_excluded.emplace_back(line.substr(1)); | ||||||
|  |             else break; // End of Files-Excluded block
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return files_excluded; | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								cpp/fs_common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								cpp/fs_common.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | |||||||
|  | // Copyright (C) 2024-2025 Simon Quigley <tsimonq2@ubuntu.com>
 | ||||||
|  | //
 | ||||||
|  | // 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 <https://www.gnu.org/licenses/>.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <filesystem> | ||||||
|  | #include <regex> | ||||||
|  | #include <vector> | ||||||
|  | 
 | ||||||
|  | namespace fs = std::filesystem; | ||||||
|  | 
 | ||||||
|  | // Function to read the entire content of a file into a string
 | ||||||
|  | std::string read_file(const std::filesystem::path& file_path); | ||||||
|  | 
 | ||||||
|  | // Function to write a string into a file
 | ||||||
|  | void write_file(const std::filesystem::path& file_path, const std::string& content); | ||||||
|  | 
 | ||||||
|  | // Function to perform in-place regex replace on a file
 | ||||||
|  | void regex_replace_in_file(const std::filesystem::path& file_path, const std::string& pattern, const std::string& replace); | ||||||
|  | 
 | ||||||
|  | // Function to create a temporary directory with a random name
 | ||||||
|  | std::filesystem::path create_temp_directory(); | ||||||
|  | 
 | ||||||
|  | // Function to copy a directory recursively
 | ||||||
|  | void copy_directory(const std::filesystem::path& source, const std::filesystem::path& destination); | ||||||
|  | 
 | ||||||
|  | // Function to extract excluded files from a copyright file
 | ||||||
|  | std::vector<std::string> extract_files_excluded(const std::string& filepath); | ||||||
| @ -13,6 +13,7 @@ | |||||||
| // You should have received a copy of the GNU General Public License
 | // You should have received a copy of the GNU General Public License
 | ||||||
| // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | // along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | ||||||
| 
 | 
 | ||||||
|  | #include "fs_common.h" | ||||||
| #include "update-maintainer-lib.h" | #include "update-maintainer-lib.h" | ||||||
| #include <filesystem> | #include <filesystem> | ||||||
| #include <fstream> | #include <fstream> | ||||||
| @ -56,20 +57,6 @@ static bool xsbc_managed_by_rules(const fs::path &debian_dir) { | |||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static std::string read_file(const fs::path &p) { |  | ||||||
|     std::ifstream f(p); |  | ||||||
|     if(!f) throw std::runtime_error("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 std::runtime_error("Cannot write file: " + p.string()); |  | ||||||
|     f << content; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void update_maintainer_file(const fs::path &control_file, bool verbose) { | static void update_maintainer_file(const fs::path &control_file, bool verbose) { | ||||||
|     std::string c = read_file(control_file); |     std::string c = read_file(control_file); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -41,33 +41,6 @@ static std::counting_semaphore<10> sem(10); | |||||||
| static std::mutex queue_mutex; | static std::mutex queue_mutex; | ||||||
| static std::atomic<bool> daemon_running{false}; | static std::atomic<bool> daemon_running{false}; | ||||||
| 
 | 
 | ||||||
| // Function to read the entire content of a file into a string
 |  | ||||||
| std::string read_file(const fs::path& file_path) { |  | ||||||
|     std::ifstream in_file(file_path, std::ios::binary); |  | ||||||
|     if (in_file) { |  | ||||||
|         return std::string((std::istreambuf_iterator<char>(in_file)), |  | ||||||
|                            std::istreambuf_iterator<char>()); |  | ||||||
|     } |  | ||||||
|     return ""; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Function to write a string into a file
 |  | ||||||
| void write_file(const fs::path& file_path, const std::string& content) { |  | ||||||
|     std::ofstream out_file(file_path, std::ios::binary); |  | ||||||
|     if (out_file) { |  | ||||||
|         out_file << content; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Function to perform in-place regex replace on a file
 |  | ||||||
| void regex_replace_in_file(const fs::path& file_path, |  | ||||||
|                            const std::string& pattern, |  | ||||||
|                            const std::string& replacement) { |  | ||||||
|     std::string content = read_file(file_path); |  | ||||||
|     content = std::regex_replace(content, std::regex(pattern), replacement); |  | ||||||
|     write_file(file_path, content); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Function to decompress gzipped files
 | // Function to decompress gzipped files
 | ||||||
| std::string decompress_gzip(const fs::path& file_path) { | std::string decompress_gzip(const fs::path& file_path) { | ||||||
|     gzFile infile = gzopen(file_path.c_str(), "rb"); |     gzFile infile = gzopen(file_path.c_str(), "rb"); | ||||||
| @ -151,38 +124,6 @@ void download_file_with_timestamping(const std::string& url, | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::filesystem::path create_temp_directory() { |  | ||||||
|     auto temp_dir = std::filesystem::temp_directory_path() / generate_random_string(32); |  | ||||||
|     std::filesystem::create_directory(temp_dir); |  | ||||||
|     return temp_dir; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Function to copy a directory recursively
 |  | ||||||
| void copy_directory(const fs::path& source, const fs::path& destination) { |  | ||||||
|     if (!std::filesystem::exists(source) || !std::filesystem::is_directory(source)) { |  | ||||||
|         throw std::runtime_error("Source directory does not exist or is not a directory: " + source.string()); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Create the destination directory
 |  | ||||||
|     std::filesystem::create_directories(destination); |  | ||||||
| 
 |  | ||||||
|     // Copy files and directories recursively
 |  | ||||||
|     for (const auto& entry : std::filesystem::recursive_directory_iterator(source)) { |  | ||||||
|         auto relative_path = std::filesystem::relative(entry.path(), source); |  | ||||||
|         auto target_path = destination / relative_path; |  | ||||||
| 
 |  | ||||||
|         try { |  | ||||||
|             if (std::filesystem::is_directory(entry)) { |  | ||||||
|                 std::filesystem::create_directory(target_path); |  | ||||||
|             } else if (std::filesystem::is_regular_file(entry)) { |  | ||||||
|                 std::filesystem::copy(entry, target_path, std::filesystem::copy_options::overwrite_existing); |  | ||||||
|             } |  | ||||||
|         } catch (...) { |  | ||||||
|             continue; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Function to generate a random string of given length
 | // Function to generate a random string of given length
 | ||||||
| std::string generate_random_string(size_t length) { | std::string generate_random_string(size_t length) { | ||||||
|     const std::string chars = |     const std::string chars = | ||||||
| @ -301,8 +242,6 @@ void log_verbose(const std::string &msg) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| namespace fs = std::filesystem; |  | ||||||
| 
 |  | ||||||
| bool run_command(const std::vector<std::string> &cmd, | bool run_command(const std::vector<std::string> &cmd, | ||||||
|                  const std::optional<std::filesystem::path> &cwd, |                  const std::optional<std::filesystem::path> &cwd, | ||||||
|                  bool show_output, |                  bool show_output, | ||||||
| @ -368,34 +307,3 @@ bool run_command(const std::vector<std::string> &cmd, | |||||||
| 
 | 
 | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // Function to extract excluded files from a copyright file
 |  | ||||||
| std::vector<std::string> extract_files_excluded(const std::string& filepath) { |  | ||||||
|     std::ifstream file(filepath); |  | ||||||
|     if (!file.is_open()) { |  | ||||||
|         throw std::runtime_error("Failed to open file: " + filepath); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     std::vector<std::string> files_excluded; |  | ||||||
|     std::string line; |  | ||||||
|     std::regex files_excluded_pattern(R"(Files-Excluded:\s*(.*))"); |  | ||||||
|     bool in_files_excluded = false; |  | ||||||
| 
 |  | ||||||
|     while (std::getline(file, line)) { |  | ||||||
|         if (std::regex_match(line, files_excluded_pattern)) { |  | ||||||
|             in_files_excluded = true; |  | ||||||
|             std::smatch match; |  | ||||||
|             if (std::regex_search(line, match, files_excluded_pattern) && match.size() > 1) { |  | ||||||
|                 files_excluded.emplace_back(match[1]); |  | ||||||
|             } |  | ||||||
|         } else if (in_files_excluded) { |  | ||||||
|             if (!line.empty() && (line[0] == ' ' || line[0] == '\t')) { |  | ||||||
|                 files_excluded.emplace_back(line.substr(1)); |  | ||||||
|             } else { |  | ||||||
|                 break; // End of Files-Excluded block
 |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return files_excluded; |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -15,14 +15,15 @@ | |||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <string> |  | ||||||
| #include <filesystem> | #include <filesystem> | ||||||
|  | #include <functional> | ||||||
|  | #include <future> | ||||||
| #include <mutex> | #include <mutex> | ||||||
| #include <regex> | #include <regex> | ||||||
| #include <future> |  | ||||||
| #include <shared_mutex> | #include <shared_mutex> | ||||||
| #include <semaphore> | #include <semaphore> | ||||||
| #include <functional> | #include <string> | ||||||
|  | 
 | ||||||
| #include <QProcess> | #include <QProcess> | ||||||
| 
 | 
 | ||||||
| namespace fs = std::filesystem; | namespace fs = std::filesystem; | ||||||
| @ -68,15 +69,6 @@ public: | |||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // Function to read the entire content of a file into a string
 |  | ||||||
| std::string read_file(const std::filesystem::path& filePath); |  | ||||||
| 
 |  | ||||||
| // Function to write a string into a file
 |  | ||||||
| void write_file(const std::filesystem::path& filePath, const std::string& content); |  | ||||||
| 
 |  | ||||||
| // Function to perform in-place regex replace on a file
 |  | ||||||
| void regex_replace_in_file(const std::filesystem::path& filePath, const std::string& pattern, const std::string& replace); |  | ||||||
| 
 |  | ||||||
| // Function to decompress gzipped files
 | // Function to decompress gzipped files
 | ||||||
| std::string decompress_gzip(const std::filesystem::path& filePath); | std::string decompress_gzip(const std::filesystem::path& filePath); | ||||||
| 
 | 
 | ||||||
| @ -87,12 +79,6 @@ void download_file_with_timestamping(const std::string& url, const std::filesyst | |||||||
| // Helper function for libcurl write callback
 | // Helper function for libcurl write callback
 | ||||||
| size_t write_data(void* ptr, size_t size, size_t nmemb, void* stream); | size_t write_data(void* ptr, size_t size, size_t nmemb, void* stream); | ||||||
| 
 | 
 | ||||||
| // Function to create a temporary directory with a random name
 |  | ||||||
| std::filesystem::path create_temp_directory(); |  | ||||||
| 
 |  | ||||||
| // Function to copy a directory recursively
 |  | ||||||
| void copy_directory(const std::filesystem::path& source, const std::filesystem::path& destination); |  | ||||||
| 
 |  | ||||||
| // String utilities
 | // String utilities
 | ||||||
| std::vector<std::string> split_string(const std::string& input, const std::string& delimiter); | std::vector<std::string> split_string(const std::string& input, const std::string& delimiter); | ||||||
| std::string remove_suffix(const std::string& input, const std::string& suffix); | std::string remove_suffix(const std::string& input, const std::string& suffix); | ||||||
| @ -115,6 +101,3 @@ bool run_command(const std::vector<std::string> &cmd, | |||||||
|                  const std::optional<fs::path> &cwd = std::nullopt, |                  const std::optional<fs::path> &cwd = std::nullopt, | ||||||
|                  bool show_output = false, |                  bool show_output = false, | ||||||
|                  std::shared_ptr<Log> log = nullptr); |                  std::shared_ptr<Log> log = nullptr); | ||||||
| 
 |  | ||||||
| // Function to extract excluded files from a copyright file
 |  | ||||||
| std::vector<std::string> extract_files_excluded(const std::string& filepath); |  | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user