Initial Unicode support for command line arguments on Windows

This commit is contained in:
Marcus Holland-Moritz 2023-06-26 23:59:11 +02:00
parent 1dcab5996e
commit 9163c6e24e
5 changed files with 73 additions and 17 deletions

View File

@ -21,6 +21,7 @@
#pragma once
#include <filesystem>
#include <iosfwd>
#include <memory>
#include <string>
@ -38,7 +39,9 @@ class builtin_script : public script {
builtin_script(logger& lgr);
~builtin_script();
void set_root_path(std::string const& path) { impl_->set_root_path(path); }
void set_root_path(std::filesystem::path const& path) {
impl_->set_root_path(path);
}
void add_filter_rule(std::string const& rule) {
impl_->add_filter_rule(rule);
}
@ -62,7 +65,7 @@ class builtin_script : public script {
public:
virtual ~impl() = default;
virtual void set_root_path(std::string const& path) = 0;
virtual void set_root_path(std::filesystem::path const& path) = 0;
virtual void add_filter_rule(std::string const& rule) = 0;
virtual void add_filter_rules(std::istream& is) = 0;
virtual void add_transformer(std::unique_ptr<entry_transformer>&& xfm) = 0;

View File

@ -0,0 +1,42 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/**
* \author Marcus Holland-Moritz (github@mhxnet.de)
* \copyright Copyright (c) Marcus Holland-Moritz
*
* This file is part of dwarfs.
*
* dwarfs 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.
*
* dwarfs 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 dwarfs. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <boost/program_options.hpp>
#include "dwarfs/types.h"
namespace dwarfs {
#ifdef _WIN32
template <typename T>
auto po_sys_value(T* v) {
return boost::program_options::wvalue<T>(v);
}
#else
template <typename T>
auto po_sys_value(T* v) {
return boost::program_options::value<T>(v);
}
#endif
} // namespace dwarfs

View File

@ -30,9 +30,11 @@ using file_off_t = int64_t;
#ifdef _WIN32
using sys_char = wchar_t;
using sys_string = std::wstring;
#define SYS_CERR std::wcerr
#else
using sys_char = char;
using sys_string = std::string;
#define SYS_CERR std::cerr
#endif
} // namespace dwarfs

View File

@ -30,6 +30,7 @@
#include "dwarfs/entry_interface.h"
#include "dwarfs/entry_transformer.h"
#include "dwarfs/logger.h"
#include "dwarfs/util.h"
namespace dwarfs {
@ -57,7 +58,7 @@ class builtin_script_ : public builtin_script::impl {
public:
builtin_script_(logger& lgr);
void set_root_path(std::string const& path) override;
void set_root_path(std::filesystem::path const& path) override;
void add_filter_rule(std::string const& rule) override;
void add_filter_rules(std::istream& is) override;
@ -182,8 +183,10 @@ builtin_script_<LoggerPolicy>::builtin_script_(logger& lgr)
: log_(lgr) {}
template <typename LoggerPolicy>
void builtin_script_<LoggerPolicy>::set_root_path(std::string const& path) {
root_path_ = path;
void builtin_script_<LoggerPolicy>::set_root_path(
std::filesystem::path const& path) {
// TODO: this whole thing needs to be windowsized
root_path_ = u8string_to_string(path.u8string());
}
template <typename LoggerPolicy>

View File

@ -71,6 +71,7 @@
#include "dwarfs/options.h"
#include "dwarfs/options_interface.h"
#include "dwarfs/os_access_generic.h"
#include "dwarfs/program_options_helpers.h"
#include "dwarfs/progress.h"
#include "dwarfs/scanner.h"
#include "dwarfs/script.h"
@ -378,11 +379,11 @@ int mkdwarfs_main(int argc, sys_char** argv) {
const size_t num_cpu = std::max(folly::hardware_concurrency(), 1u);
block_manager::config cfg;
std::string path, output, memory_limit, script_arg, compression, header,
schema_compression, metadata_compression, log_level_str, timestamp,
time_resolution, order, progress_mode, recompress_opts, pack_metadata,
file_hash_algo, debug_filter, max_similarity_size, input_list_str,
chmod_str;
sys_string path_str, output_str;
std::string memory_limit, script_arg, compression, header, schema_compression,
metadata_compression, log_level_str, timestamp, time_resolution, order,
progress_mode, recompress_opts, pack_metadata, file_hash_algo,
debug_filter, max_similarity_size, input_list_str, chmod_str;
std::vector<std::string> filter;
size_t num_workers, num_scanner_workers;
bool no_progress = false, remove_header = false, no_section_index = false,
@ -416,13 +417,13 @@ int mkdwarfs_main(int argc, sys_char** argv) {
po::options_description opts("Command line options");
opts.add_options()
("input,i",
po::value<std::string>(&path),
po_sys_value<sys_string>(&path_str),
"path to root directory or source filesystem")
("input-list",
po::value<std::string>(&input_list_str),
"file containing list of paths relative to root directory")
("output,o",
po::value<std::string>(&output),
po_sys_value<sys_string>(&output_str),
"filesystem output name")
("force,f",
po::value<bool>(&force_overwrite)->zero_tokens(),
@ -549,6 +550,8 @@ int mkdwarfs_main(int argc, sys_char** argv) {
po::variables_map vm;
auto& err_out = SYS_CERR;
try {
auto parsed = po::parse_command_line(argc, argv, opts);
@ -559,8 +562,8 @@ int mkdwarfs_main(int argc, sys_char** argv) {
po::collect_unrecognized(parsed.options, po::include_positional);
if (!unrecognized.empty()) {
std::wcerr << "error: unrecognized argument(s) '"
<< boost::join(unrecognized, " ") << "'" << std::endl;
err_out << "error: unrecognized argument(s) '"
<< boost::join(unrecognized, " ") << "'" << std::endl;
return 1;
}
} catch (po::error const& e) {
@ -663,6 +666,7 @@ int mkdwarfs_main(int argc, sys_char** argv) {
return 1;
}
std::filesystem::path path(path_str);
std::optional<std::vector<std::filesystem::path>> input_list;
if (vm.count("input-list")) {
@ -676,7 +680,7 @@ int mkdwarfs_main(int argc, sys_char** argv) {
options.with_specials = true;
if (!vm.count("input")) {
path = std::filesystem::current_path().string();
path = std::filesystem::current_path();
}
std::unique_ptr<std::ifstream> ifs;
@ -1046,6 +1050,8 @@ int mkdwarfs_main(int argc, sys_char** argv) {
<< " blocks with " << num_workers << " threads";
}
std::filesystem::path output(output_str);
std::unique_ptr<std::ostream> os;
if (!options.debug_filter_function) {
@ -1059,8 +1065,8 @@ int mkdwarfs_main(int argc, sys_char** argv) {
std::ios::trunc);
if (ofs->bad() || !ofs->is_open()) {
std::cerr << "error: cannot open output file '" << output
<< "': " << strerror(errno) << std::endl;
err_out << "error: cannot open output file '" << output
<< "': " << strerror(errno) << std::endl;
return 1;
}