1
0
Fork 0
mirror of https://github.com/KingDuckZ/dindexer.git synced 2025-07-03 14:14:11 +00:00

Allow tagging files by glob

Tagging by ID is still possible using the --ids switch, which takes a
comma-separated list of IDs. However only one mode is allowed at time,
so either tag by glob OR tag by ID.
This commit is contained in:
King_DuckZ 2016-05-17 19:54:05 +02:00
parent 67bdabb548
commit 21c5b3efcb
5 changed files with 54 additions and 14 deletions

View file

@ -8,11 +8,13 @@ add_executable(${PROJECT_NAME}
target_include_directories(${PROJECT_NAME} target_include_directories(${PROJECT_NAME}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/.. PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/..
PRIVATE ${CMAKE_SOURCE_DIR}/lib/glob2regex/include
) )
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME}
PRIVATE ${bare_name}-if PRIVATE ${bare_name}-if
PRIVATE ${bare_name}-common PRIVATE ${bare_name}-common
PRIVATE glob2regex
) )
string(REPLACE "${bare_name}-" "" ACTION_NAME "${PROJECT_NAME}") string(REPLACE "${bare_name}-" "" ACTION_NAME "${PROJECT_NAME}")

View file

@ -26,23 +26,24 @@ namespace po = boost::program_options;
namespace din { namespace din {
bool parse_commandline (int parArgc, char* parArgv[], po::variables_map& parVarMap) { bool parse_commandline (int parArgc, char* parArgv[], po::variables_map& parVarMap) {
po::options_description set_options(ACTION_NAME " options"); po::options_description set_options(ACTION_NAME " options");
//set_options.add_options() set_options.add_options()
//("switch,s", "Help message") //("switch,s", "Help message")
//("option,o", po::value<std::string>()->default_value("default_value"), "Help message") //("option,o", po::value<std::string>()->default_value("default_value"), "Help message")
//("option2", po::value<int>(), "Help message") //("option2", po::value<int>(), "Help message")
//; ("ids", po::value<std::string>(), "Comma-separated list of IDs of files to be tagged")
;
po::options_description positional_options("Positional options"); po::options_description positional_options("Positional options");
positional_options.add_options() positional_options.add_options()
("tags", po::value<std::string>(), "comma-separated tag list") ("tags", po::value<std::string>(), "comma-separated tag list")
("ids", po::value<std::vector<uint64_t>>(), "pos_option description") ("glob", po::value<std::string>(), "glob to match against")
; ;
const auto desc = dinlib::get_default_commandline(); const auto desc = dinlib::get_default_commandline();
po::options_description all("Available options"); po::options_description all("Available options");
po::positional_options_description pd; po::positional_options_description pd;
all.add(desc).add(positional_options).add(set_options); all.add(desc).add(positional_options).add(set_options);
pd.add("tags", 1).add("ids", -1); pd.add("tags", 1).add("glob", 1);
try { try {
po::store(po::command_line_parser(parArgc, parArgv).options(all).positional(pd).run(), parVarMap); po::store(po::command_line_parser(parArgc, parArgv).options(all).positional(pd).run(), parVarMap);
} }
@ -52,7 +53,7 @@ namespace din {
po::notify(parVarMap); po::notify(parVarMap);
const char* const help_text = "[options...] tag[,tag2...] ids..."; const char* const help_text = "[options...] tag[,tag2...] (--ids id1[,id2...] | <glob>)";
if (dinlib::manage_common_commandline(std::cout, ACTION_NAME, help_text, parVarMap, {std::cref(desc), std::cref(set_options)})) { if (dinlib::manage_common_commandline(std::cout, ACTION_NAME, help_text, parVarMap, {std::cref(desc), std::cref(set_options)})) {
return true; return true;
} }

View file

@ -20,14 +20,19 @@
#include "dindexerConfig.h" #include "dindexerConfig.h"
#include "tag_postgres.hpp" #include "tag_postgres.hpp"
#include "dindexer-common/split_tags.hpp" #include "dindexer-common/split_tags.hpp"
#include "glob2regex/glob2regex.hpp"
#include <iostream> #include <iostream>
#include <ciso646> #include <ciso646>
#include <algorithm>
#include <boost/lexical_cast.hpp>
namespace { namespace {
} //unnamed namespace } //unnamed namespace
int main (int parArgc, char* parArgv[]) { int main (int parArgc, char* parArgv[]) {
using boost::program_options::variables_map; using boost::program_options::variables_map;
using boost::lexical_cast;
using boost::string_ref;
variables_map vm; variables_map vm;
try { try {
@ -40,10 +45,17 @@ int main (int parArgc, char* parArgv[]) {
return 2; return 2;
} }
if (not vm.count("ids")) { const bool id_mode = static_cast<bool>(vm.count("ids"));
std::cerr << "No IDs specified\n"; const bool glob_mode = static_cast<bool>(vm.count("glob"));
if (not id_mode and not glob_mode) {
std::cerr << "No IDs or glob specified\n";
return 2; return 2;
} }
else if (id_mode and glob_mode) {
std::cerr << "Can't specify both a glob and IDs, please only use one of them\n";
return 2;
}
assert(id_mode xor glob_mode);
dinlib::Settings settings; dinlib::Settings settings;
{ {
@ -54,14 +66,24 @@ int main (int parArgc, char* parArgv[]) {
} }
} }
const auto ids = vm["ids"].as<std::vector<uint64_t>>(); const auto master_tags_string = vm["tags"].as<std::string>();
for (auto id : ids) { const std::vector<boost::string_ref> tags = dinlib::split_tags(master_tags_string);
std::cout << id << '\n';
if (id_mode) {
auto ids_string = dinlib::split_tags(vm["ids"].as<std::string>());
std::vector<uint64_t> ids;
ids.reserve(ids_string.size());
std::transform(ids_string.begin(), ids_string.end(), std::back_inserter(ids), &lexical_cast<uint64_t, string_ref>);
din::tag_files(settings.db, ids, tags);
}
else if (glob_mode) {
const auto regex = g2r::convert(vm["glob"].as<std::string>());
din::tag_files(settings.db, regex, true, tags);
}
else {
assert(false);
return 1;
} }
const auto master_tags_string = vm["tags"].as<std::string>();
std::vector<boost::string_ref> tags = dinlib::split_tags(master_tags_string);
din::tag_files(settings.db, ids, tags);
return 0; return 0;
} }

View file

@ -18,6 +18,7 @@
#include "tag_postgres.hpp" #include "tag_postgres.hpp"
#include "pq/connection.hpp" #include "pq/connection.hpp"
#include "dindexer-common/settings.hpp" #include "dindexer-common/settings.hpp"
#include <ciso646>
namespace din { namespace din {
void tag_files (const dinlib::SettingsDB& parDB, const std::vector<uint64_t>& parFiles, const std::vector<boost::string_ref>& parTags) { void tag_files (const dinlib::SettingsDB& parDB, const std::vector<uint64_t>& parFiles, const std::vector<boost::string_ref>& parTags) {
@ -29,4 +30,17 @@ namespace din {
conn.query(query, parTags, parFiles); conn.query(query, parTags, parFiles);
} }
void tag_files (const dinlib::SettingsDB& parDB, std::string parRegex, bool parCaseSensitive, const std::vector<boost::string_ref>& parTags) {
pq::Connection conn(std::string(parDB.username), std::string(parDB.password), std::string(parDB.dbname), std::string(parDB.address), parDB.port);
conn.connect();
if (not parCaseSensitive)
parRegex = "(?i)" + parRegex;
const std::string query =
"UPDATE \"files\" SET \"tags\" = ARRAY(SELECT DISTINCT UNNEST(\"tags\" || $1) ORDER BY 1) WHERE \"path\" ~ $2;";
conn.query(query, parTags, parRegex);
}
} //namespace din } //namespace din

View file

@ -28,6 +28,7 @@ namespace dinlib {
namespace din { namespace din {
void tag_files ( const dinlib::SettingsDB& parDB, const std::vector<uint64_t>& parFiles, const std::vector<boost::string_ref>& parTags ); void tag_files ( const dinlib::SettingsDB& parDB, const std::vector<uint64_t>& parFiles, const std::vector<boost::string_ref>& parTags );
void tag_files ( const dinlib::SettingsDB& parDB, std::string parRegex, bool parCaseSensitive, const std::vector<boost::string_ref>& parTags );
} //namespace din } //namespace din
#endif #endif