17 #include "addon/manager.hpp"
27 #include <boost/algorithm/string.hpp>
30 #define ERR_CFG LOG_STREAM(err , log_config)
31 #define LOG_CFG LOG_STREAM(info, log_config)
32 #define WRN_CFG LOG_STREAM(warn, log_config)
35 #define ERR_FS LOG_STREAM(err , log_filesystem)
38 #define ERR_NET LOG_STREAM(err , log_network)
39 #define LOG_NET LOG_STREAM(info, log_network)
42 std::string get_pbl_file_path(
const std::string& addon_name)
46 const std::string exterior = parentd +
"/" + addon_name +
".pbl";
47 const std::string interior = parentd +
"/" + addon_name +
"/_server.pbl";
51 inline std::string get_info_file_path(
const std::string& addon_name)
74 const std::string& pbl_path = get_pbl_file_path(addon_name);
77 std::unique_ptr<schema_validation::schema_validator>
validator;
86 auto msg =
e.user_message;
87 e.user_message +=
" in " + addon_name;
109 const std::string& info_path = get_info_file_path(addon_name);
116 read(envelope, *stream);
118 cfg = std::move(*
info);
121 ERR_CFG <<
"Failed to read add-on installation information for '"
122 << addon_name <<
"' from " << info_path <<
":\n"
129 LOG_CFG <<
"Writing version info for add-on '" << addon_name <<
"'";
131 const auto& info_path = get_info_file_path(addon_name);
135 <<
"# File automatically generated by Wesnoth to keep track\n"
136 <<
"# of version information on installed add-ons. DO NOT EDIT!\n"
141 write(*out, envelope);
148 LOG_CFG <<
"removing local add-on: " << addon;
151 ERR_CFG <<
"Failed to delete directory/file: " << addon_dir;
152 ERR_CFG <<
"removal of add-on " << addon <<
" failed!";
160 enum ADDON_ENUM_CRITERIA
166 std::vector<std::string> enumerate_addons_internal(ADDON_ENUM_CRITERIA filter)
168 std::vector<std::string> res;
169 std::vector<std::string> addon_dirnames;
174 for(
const auto& addon_name : addon_dirnames) {
178 res.emplace_back(addon_name);
189 return enumerate_addons_internal(ADDON_HAS_PBL);
194 return enumerate_addons_internal(ADDON_ANY);
199 std::map<std::string, std::string> addons;
207 addons[addon_id] =
"Invalid pbl file, version unknown";
212 addons[addon_id] = !info_cfg.
empty() ? info_cfg[
"version"].str() :
"Unknown";
214 addons[addon_id] =
"Unknown";
226 static inline bool IsCR(
const char&
c)
231 static std::string
strip_cr(std::string str,
bool strip)
242 const std::string ign_file = parentd +
"/" + addon_name +
"/_server.ign";
245 LOG_CFG <<
"searching for .ign file for '" << addon_name <<
"'...";
247 LOG_CFG <<
"no .ign file found for '" << addon_name <<
"'\n"
248 <<
"using default ignore patterns...";
251 LOG_CFG <<
"found .ign file: " << ign_file;
254 while (std::getline(*stream,
line)) {
256 const std::size_t l =
line.size();
258 if (l == 0 || !
line.compare(0,2,
"# "))
continue;
259 if (
line[l - 1] ==
'/') {
276 cfg[
"name"] = dirname;
277 const std::string dir =
path +
'/' + dirname;
279 std::vector<std::string> files, dirs;
281 for(
const std::string& name : files) {
288 for(
const std::string& name : dirs) {
289 bool valid = !ignore_patterns.
match_dir(name);
312 if (cfg[
"name"].empty())
315 dir =
path +
'/' + cfg[
"name"].str();
345 unsigned file_count = progress_callback ?
count_pack_files(cfg) : 0, done = 0;
346 auto file_callback = progress_callback
347 ? [&]() { progress_callback(++done * 100.0 / file_count); }
348 : std::function<void()>{};
355 if(removelist[
"name"].empty())
358 dir =
path +
'/' + removelist[
"name"].str();
384 std::map< std::string, version_info > version_info_cache;
389 version_info_cache.clear();
391 LOG_CFG <<
"refreshing add-on versions cache";
398 std::vector<std::string> addon_info_files(addons.size());
400 std::transform(addons.begin(), addons.end(),
401 addon_info_files.begin(), get_info_file_path);
403 for(std::size_t
i = 0;
i < addon_info_files.size(); ++
i) {
404 assert(
i < addons.size());
406 const std::string& addon = addons[
i];
407 const std::string& info_file = addon_info_files[
i];
413 if(info_cfg.
empty()) {
417 const std::string& version = info_cfg[
"version"].str();
418 LOG_CFG <<
"cached add-on version: " << addon <<
" [" << version <<
"]";
420 version_info_cache[addon] = version;
423 WRN_CFG <<
"add-on '" << addon <<
"' has no _info.cfg; cannot read version info";
432 return entry != version_info_cache.end() ? entry->second : nil;
static void archive_file(const std::string &path, const std::string &fname, config &cfg)
bool remove_local_addon(const std::string &addon)
Removes the specified add-on, deleting its full directory structure.
static bool IsCR(const char &c)
config get_addon_pbl_info(const std::string &addon_name, bool do_validate)
Gets the publish information for an add-on.
void unarchive_addon(const config &cfg, std::function< void(unsigned)> progress_callback)
bool have_addon_in_vcs_tree(const std::string &addon_name)
Returns whether the specified add-on appears to be managed by a VCS or not.
void set_addon_pbl_info(const std::string &addon_name, const config &cfg)
static lg::log_domain log_filesystem("filesystem")
void purge_addon(const config &removelist)
Removes the listed files from the addon.
static void unarchive_dir(const std::string &path, const config &cfg, std::function< void()> file_callback={})
static void archive_dir(const std::string &path, const std::string &dirname, config &cfg, const filesystem::blacklist_pattern_list &ignore_patterns)
void archive_addon(const std::string &addon_name, config &cfg)
Archives an add-on into a config object for campaignd transactions.
static void purge_dir(const std::string &path, const config &removelist)
void get_addon_install_info(const std::string &addon_name, config &cfg)
Gets the installation info (_info.cfg) for an add-on.
void write_addon_install_info(const std::string &addon_name, const config &cfg)
static lg::log_domain log_network("network")
static unsigned count_pack_files(const config &cfg)
static std::string strip_cr(std::string str, bool strip)
std::map< std::string, std::string > installed_addons_and_versions()
Retrieves the ids and versions of all installed add-ons.
bool have_addon_pbl_info(const std::string &addon_name)
Returns whether a .pbl file is present for the specified add-on or not.
std::vector< std::string > available_addons()
Returns a list of local add-ons that can be published.
std::vector< std::string > installed_addons()
Retrieves the names of all installed add-ons.
bool have_addon_install_info(const std::string &addon_name)
Returns true if there is a local installation info (_info.cfg) file for the add-on.
static void unarchive_file(const std::string &path, const config &cfg)
void refresh_addon_version_info_cache()
Refreshes the per-session cache of add-on's version information structs.
version_info get_addon_version_info(const std::string &addon)
Returns a particular installed add-on's version information.
bool is_addon_installed(const std::string &addon_name)
Check whether the specified add-on is currently installed.
static filesystem::blacklist_pattern_list read_ignore_patterns(const std::string &addon_name)
static lg::log_domain log_config("config")
A config object defines a single node in a WML file, with access to child nodes.
std::size_t child_count(config_key_type key) const
child_itors child_range(config_key_type key)
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Equivalent to mandatory_child, but returns an empty optional if the nth child was not found.
config & add_child(config_key_type key)
bool match_file(const std::string &name) const
void add_file_pattern(const std::string &pattern)
void add_directory_pattern(const std::string &pattern)
bool match_dir(const std::string &name) const
Represents version numbers.
Declarations for File-IO.
Interfaces for manipulating version numbers of engine, add-ons, etc.
Standard logging facilities (interface).
void line(int from_x, int from_y, int to_x, int to_y)
Draw a line.
int dir_size(const std::string &pname)
Returns the sum of the sizes of the files contained in a directory.
filesystem::scoped_istream istream_file(const std::string &fname, bool treat_failure_as_error)
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs, name_mode mode, filter_mode filter, reorder_mode reorder, file_tree_checksum *checksum)
Get a list of all files and/or directories in a given directory.
bool is_cfg(const std::string &filename)
Returns true if the file ends with the wmlfile extension.
bool delete_file(const std::string &filename)
static bool file_exists(const bfs::path &fpath)
bool is_directory(const std::string &fname)
Returns true if the given file is a directory.
bool delete_directory(const std::string &dirname, const bool keep_pbl)
utils::optional< std::string > get_wml_location(const std::string &path, const utils::optional< std::string > ¤t_dir)
Returns a translated path to the actual file or directory, if it exists.
std::string read_file(const std::string &fname)
Basic disk I/O - read file.
filesystem::scoped_ostream ostream_file(const std::string &fname, std::ios_base::openmode mode, bool create_directory)
std::unique_ptr< std::istream > scoped_istream
void write_file(const std::string &fname, const std::string &data, std::ios_base::openmode mode)
Throws io_exception if an error occurs.
std::unique_ptr< std::ostream > scoped_ostream
bool looks_like_pbl(const std::string &file)
bool make_directory(const std::string &dirname)
const blacklist_pattern_list default_blacklist
std::string get_addons_dir()
std::string sanitize_path(const std::string &path)
Sanitizes a path to remove references to the user's name.
void trim(std::string_view &s)
void erase_if(Container &container, const Predicate &predicate)
Convenience wrapper for using std::remove_if on a container.
std::string::const_iterator iterator
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
One of the realizations of serialization/validator.hpp abstract validator.
void read(config &cfg, std::istream &in, abstract_validator *validator)
void write(std::ostream &out, const configr_of &cfg, unsigned int level)
Exception thrown when the WML parser fails to read a .pbl file.
Helper class, don't construct this directly.
std::string unencode_binary(const std::string &str)
std::string encode_binary(const std::string &str)
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...