Minor bug fixes and improvements

- Update `README.md` file with minor changes
- Added `max_results` parameter to config for persistence
- Added `csv2`, `tabulate`, and `indicators` as included dependencies
- Added downloading progress bar that *sometimes* work
-Added HTTP request header handling with curl
- Added more options to some commands
- Moved `http` functions into `context` class

TODO: Fix optional parameters not working correctly
NOTE: Github does not always return `Content-length` HTTP response header
This commit is contained in:
David Allen 2023-06-25 20:00:58 -06:00
parent a3e4c054c2
commit 460e2054c2
15 changed files with 408 additions and 101 deletions

View file

@ -27,6 +27,7 @@ namespace gdpm::config{
string_map remote_sources;
size_t jobs = 1;
size_t timeout = 3000;
size_t max_results = 200;
bool enable_sync = true;
bool enable_cache = true;
bool skip_prompt = false;

View file

@ -3,9 +3,12 @@
#include "constants.hpp"
#include "types.hpp"
#include <unordered_map>
#include <curl/curl.h>
#include <curl/easy.h>
namespace gdpm::http{
using headers_t = std::unordered_map<string, string>;
using header = std::pair<string, string>;
// REF: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
enum response_code{
@ -88,9 +91,25 @@ namespace gdpm::http{
int verbose = 0;
};
string url_escape(const string& url);
response request_get(const string& url, const http::request_params& params = http::request_params());
response request_post(const string& url, const http::request_params& params = http::request_params());
response download_file(const string& url, const string& storage_path, const http::request_params& params = http::request_params());
class context : public non_copyable{
public:
context();
~context();
inline CURL* const get_curl() const;
string url_escape(const string& url);
response request_get(const string& url, const http::request_params& params = http::request_params());
response request_post(const string& url, const http::request_params& params = http::request_params());
response download_file(const string& url, const string& storage_path, const http::request_params& params = http::request_params());
long get_download_size(const string& url);
long get_bytes_downloaded(const string& url);
private:
CURL *curl;
curl_slist* _add_headers(CURL *curl, const headers_t& headers);
};
extern context http;
}

View file

@ -90,21 +90,21 @@ namespace gdpm::package {
To copy the package to a project instead of linking, use the `--clone` option.
`gdpm install --clone "super cool examle package"
`gdpm install --clone "super cool example package"
*/
GDPM_DLL_EXPORT error install(const config::context& config, const title_list& package_titles, const params& params = package::params());
GDPM_DLL_EXPORT error install(const config::context& config, title_list& package_titles, const params& params = package::params());
/*!
@brief Adds package to project locally only.
@param config
@param package_titles
@param params
*/
GDPM_DLL_EXPORT error add(const config::context& config, const title_list& package_titles, const params& params = package::params());
GDPM_DLL_EXPORT error add(const config::context& config, title_list& package_titles, const params& params = package::params());
/*!
@brief Remove's package and contents from local database.
*/
GDPM_DLL_EXPORT error remove(const config::context& config, const title_list& package_titles, const params& params = package::params());
GDPM_DLL_EXPORT error remove(const config::context& config, title_list& package_titles, const params& params = package::params());
GDPM_DLL_EXPORT error remove_all(const config::context& config, const params& params = package::params());
GDPM_DLL_EXPORT error update(const config::context& config, const title_list& package_titles, const params& params = package::params());
GDPM_DLL_EXPORT error search(const config::context& config, const title_list& package_titles, const params& params = package::params());

View file

@ -17,10 +17,12 @@
#include <fmt/format.h>
#include <fmt/chrono.h>
typedef long curl_off_t;
namespace gdpm::utils {
using namespace std::chrono_literals;
// extern indicators::DynamicProgress<indicators::ProgressBar> bars;
struct memory_buffer{
char *addr = nullptr;
size_t size = 0;
@ -37,31 +39,6 @@ namespace gdpm::utils {
free(buf.addr);
}
static size_t curl_write_to_buffer(char *contents, size_t size, size_t nmemb, void *userdata){
size_t realsize = size * nmemb;
struct memory_buffer *m = (struct memory_buffer*)userdata;
m->addr = (char*)realloc(m->addr, m->size + realsize + 1);
if(m->addr == nullptr){
/* Out of memory */
fprintf(stderr, "Not enough memory (realloc returned NULL)\n");
return 0;
}
memcpy(&(m->addr[m->size]), contents, realsize);
m->size += realsize;
m->addr[m->size] = 0;
return realsize;
}
static size_t curl_write_to_stream(char *ptr, size_t size, size_t nmemb, void *userdata){
if(nmemb == 0)
return 0;
return fwrite(ptr, size, nmemb, (FILE*)userdata);
}
/* Use ISO 8601 for default timestamp format. */
static inline auto timestamp(const std::string& format = GDPM_TIMESTAMP_FORMAT){
time_t t = std::time(nullptr);
@ -94,7 +71,8 @@ namespace gdpm::utils {
std::move(part, from.end(), std::back_inserter(from));
from.erase(part);
}
std::vector<std::string> split_lines(const std::string& contents);
std::string readfile(const std::string& path);
std::string to_lower(const std::string& s);
std::string trim(const std::string& s);
@ -111,8 +89,14 @@ namespace gdpm::utils {
void delay(std::chrono::milliseconds milliseconds = GDPM_REQUEST_DELAY);
std::string join(const std::vector<std::string>& target, const std::string& delimiter = ", ");
std::string join(const std::unordered_map<std::string, std::string>& target, const std::string& prefix = "", const std::string& delimiter = "\n");
std::string convert_size(long size);
// TODO: Add function to get size of decompressed zip
namespace curl {
extern size_t write_to_buffer(char *contents, size_t size, size_t nmemb, void *userdata);
extern size_t write_to_stream(char *ptr, size_t size, size_t nmemb, void *userdata);
extern int show_progress(void *ptr, curl_off_t total_download, curl_off_t current_downloaded, curl_off_t total_upload, curl_off_t current_upload);
}
namespace json {
std::string from_array(const std::set<std::string>& a, const std::string& prefix);
std::string from_object(const std::unordered_map<std::string, std::string>& m, const std::string& prefix, const std::string& spaces);