👷 gucc: add helper function to fetch file from url

This commit is contained in:
Vladislav Nepogodin 2024-07-11 02:41:29 +04:00
parent 4a6650b869
commit 464e9b3388
No known key found for this signature in database
GPG Key ID: B62C3D10C54D5DA9
9 changed files with 122 additions and 2 deletions

View File

@ -42,6 +42,7 @@ jobs:
./gucc/tests/test-fstab_gen
./gucc/tests/test-crypttab_gen
./gucc/tests/test-grub_config_gen
./gucc/tests/test-fetch_file
shell: bash
build-cmake_withoutdev:
name: Build with CMake (DEVENV OFF)
@ -90,6 +91,7 @@ jobs:
./gucc/tests/test-fstab_gen
./gucc/tests/test-crypttab_gen
./gucc/tests/test-grub_config_gen
./gucc/tests/test-fetch_file
shell: bash
build-meson_withoutdev:
name: Build with Meson (DEVENV OFF)

View File

@ -32,13 +32,14 @@ add_library(${PROJECT_NAME} #SHARED
src/hwclock.cpp include/gucc/hwclock.hpp
src/package_profiles.cpp include/gucc/package_profiles.hpp
src/logger.cpp include/gucc/logger.hpp
src/fetch_file.cpp include/gucc/fetch_file.hpp
#src/chwd_profiles.cpp src/chwd_profiles.hpp
#src/disk.cpp src/disk.hpp
)
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_DIR}/include)
target_link_libraries(${PROJECT_NAME} PUBLIC project_warnings project_options spdlog::spdlog fmt::fmt range-v3::range-v3 tomlplusplus::tomlplusplus)
target_link_libraries(${PROJECT_NAME} PUBLIC project_warnings project_options spdlog::spdlog fmt::fmt range-v3::range-v3 tomlplusplus::tomlplusplus cpr::cpr)
if(COS_INSTALLER_BUILD_TESTS)
add_subdirectory(tests)

View File

@ -0,0 +1,15 @@
#ifndef FETCH_FILE_HPP
#define FETCH_FILE_HPP
#include <optional> // for optional
#include <string> // for string
#include <string_view> // for string_view
namespace gucc::fetch {
// Fetch file from url into memory
auto fetch_file_from_url(std::string_view url, std::string_view fallback_url) noexcept -> std::optional<std::string>;
} // namespace gucc::fetch
#endif // FETCH_FILE_HPP

View File

@ -22,6 +22,7 @@ gucc_lib = library('gucc',
'src/hwclock.cpp',
'src/package_profiles.cpp',
'src/logger.cpp',
'src/fetch_file.cpp',
],
include_directories : [include_directories('include')],
dependencies: deps

45
gucc/src/fetch_file.cpp Normal file
View File

@ -0,0 +1,45 @@
#include "gucc/fetch_file.hpp"
#include <chrono> // for chrono_literals
#include <cpr/api.h>
#include <cpr/response.h>
#include <cpr/status_codes.h>
#include <cpr/timeout.h>
using namespace std::string_view_literals;
namespace {
auto fetch_file(std::string_view url) noexcept -> std::optional<std::string> {
using namespace std::chrono_literals;
auto timeout = cpr::Timeout{30s};
auto response = cpr::Get(cpr::Url{url}, timeout);
auto status_code = static_cast<std::int32_t>(response.status_code);
static constexpr auto FILE_URL_PREFIX = "file://"sv;
if (cpr::status::is_success(status_code) || (url.starts_with(FILE_URL_PREFIX) && status_code == 0 && !response.text.empty())) {
return std::make_optional<std::string>(std::move(response.text));
}
return std::nullopt;
}
} // namespace
namespace gucc::fetch {
auto fetch_file_from_url(std::string_view url, std::string_view fallback_url) noexcept -> std::optional<std::string> {
auto fetch_content = fetch_file(url);
if (fetch_content) {
return std::make_optional<std::string>(std::move(*fetch_content));
}
fetch_content = fetch_file(fallback_url);
if (fetch_content) {
return std::make_optional<std::string>(std::move(*fetch_content));
}
return std::nullopt;
}
} // namespace gucc::fetch

View File

@ -4,7 +4,8 @@
file(GLOB files unit-*.cpp)
set(GUCC_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}/")
set(GUCC_TEST_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(GUCC_TOP_DIR "${CMAKE_SOURCE_DIR}")
foreach(file ${files})
get_filename_component(file_basename ${file} NAME_WE)
@ -16,5 +17,6 @@ foreach(file ${files})
$<$<CXX_COMPILER_ID:GNU>:-Wno-deprecated-declarations>
)
add_definitions(-DGUCC_TEST_DIR="${GUCC_TEST_DIR}")
add_definitions(-DGUCC_TOP_DIR="${GUCC_TOP_DIR}")
target_link_libraries(${testcase} PRIVATE project_warnings project_options gucc::gucc)
endforeach()

View File

@ -61,3 +61,11 @@ executable(
link_with: [gucc_lib],
include_directories: [include_directories('../include')],
install: false)
executable(
'test-fetch_file',
files('unit-fetch_file.cpp'),
dependencies: deps,
link_with: [gucc_lib],
include_directories: [include_directories('../include')],
install: false)

View File

@ -0,0 +1,45 @@
#include "gucc/fetch_file.hpp"
#include "gucc/file_utils.hpp"
#include <cassert>
#include <filesystem>
#include <string_view>
#include <fmt/format.h>
namespace fs = std::filesystem;
using namespace std::string_view_literals;
int main() {
// existing remote url, non existent fallback url
static constexpr std::string_view LICENSE_PATH = GUCC_TOP_DIR "/LICENSE";
{
static constexpr auto remote_url = "https://github.com/CachyOS/New-Cli-Installer/raw/master/LICENSE"sv;
const auto& file_content = gucc::fetch::fetch_file_from_url(remote_url, "file:///ter-testunit");
assert(file_content);
assert(!file_content->empty());
const auto& expected_file_content = gucc::file_utils::read_whole_file(LICENSE_PATH);
assert(file_content == expected_file_content);
}
// non existent remote url, existing fallback url
{
static constexpr auto remote_url = "https://github.com/CachyOS/New-Cli-Installer/raw/master/LCNS"sv;
const auto& file_content = gucc::fetch::fetch_file_from_url(remote_url, fmt::format("file://{}", LICENSE_PATH));
assert(file_content);
assert(!file_content->empty());
const auto& expected_file_content = gucc::file_utils::read_whole_file(LICENSE_PATH);
assert(file_content == expected_file_content);
}
// non existent remote url, non existent fallback url
{
static constexpr auto remote_url = "https://github.com/CachyOS/New-Cli-Installer/raw/master/LCNS"sv;
const auto& file_content = gucc::fetch::fetch_file_from_url(remote_url, "file:///ter-testunit");
assert(!file_content);
}
}

View File

@ -55,6 +55,7 @@ add_global_arguments('-DINSTALLER_VERSION="' + git_version + '"', language : 'cp
# gucc test path
add_global_arguments('-DGUCC_TEST_DIR="' + meson.current_source_dir() + '/gucc/tests/"', language : 'cpp')
add_global_arguments('-DGUCC_TOP_DIR="' + meson.current_source_dir() + '/"', language : 'cpp')
# Common dependencies
spdlog = dependency('spdlog', version : ['>=1.12.0'], fallback : ['spdlog', 'spdlog_dep'])