From: Arvin Schnell Date: Wed, 15 Apr 2015 09:28:16 +0000 (+0200) Subject: - sort files according to locale X-Git-Tag: v0.2.8~13^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2d7501a00517aed655ba7bd96734ae4c67d58974;p=thirdparty%2Fsnapper.git - sort files according to locale --- diff --git a/LIBVERSION b/LIBVERSION index 4a36342f..fd2a0186 100644 --- a/LIBVERSION +++ b/LIBVERSION @@ -1 +1 @@ -3.0.0 +3.1.0 diff --git a/client/commands.cc b/client/commands.cc index 6cb865d4..c046ab17 100644 --- a/client/commands.cc +++ b/client/commands.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) [2012-2014] Novell, Inc. + * Copyright (c) [2012-2015] Novell, Inc. * * All Rights Reserved. * @@ -351,6 +351,13 @@ command_delete_xcomparison(DBus::Connection& conn, const string& config_name, un } +int +operator<(const XFile& lhs, const XFile& rhs) +{ + return File::cmp_lt(lhs.name, rhs.name); +} + + list command_get_xfiles(DBus::Connection& conn, const string& config_name, unsigned int number1, unsigned int number2) @@ -367,6 +374,9 @@ command_get_xfiles(DBus::Connection& conn, const string& config_name, unsigned i DBus::Hihi hihi(reply); hihi >> files; + files.sort(); // snapperd can have different locale than client + // so sorting is required here + return files; } diff --git a/client/snapper.cc b/client/snapper.cc index a34dfc30..47b82368 100644 --- a/client/snapper.cc +++ b/client/snapper.cc @@ -1553,7 +1553,7 @@ help(const list& cmds) int main(int argc, char** argv) { - setlocale(LC_ALL, ""); + locale::global(locale("")); setLogDo(&log_do); setLogQuery(&log_query); diff --git a/package/snapper.changes b/package/snapper.changes index ff7da09d..67bef5c6 100644 --- a/package/snapper.changes +++ b/package/snapper.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Tue Apr 14 17:58:17 CEST 2015 - aschnell@suse.de + +- sort files according to locale + ------------------------------------------------------------------- Tue Mar 03 10:22:28 CET 2015 - aschnell@suse.de diff --git a/snapper/File.cc b/snapper/File.cc index d62754eb..17a4aab4 100644 --- a/snapper/File.cc +++ b/snapper/File.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) [2011-2014] Novell, Inc. + * Copyright (c) [2011-2015] Novell, Inc. * * All Rights Reserved. * @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "snapper/File.h" @@ -72,33 +73,34 @@ namespace snapper } - struct FilterHelper + void + Files::filter(const vector& ignore_patterns) { - FilterHelper(const vector& patterns) - : patterns(patterns) {} - bool operator()(const File& file) - { - for (vector::const_iterator it = patterns.begin(); it != patterns.end(); ++it) - if (fnmatch(it->c_str(), file.getName().c_str(), FNM_LEADING_DIR) == 0) - return true; - return false; - } - const vector& patterns; - }; + std::function pred = [&ignore_patterns](const File& file) { + for (const string& ignore_pattern : ignore_patterns) + if (fnmatch(ignore_pattern.c_str(), file.getName().c_str(), FNM_LEADING_DIR) == 0) + return true; + return false; + }; + entries.erase(remove_if(entries.begin(), entries.end(), pred), entries.end()); + } - void - Files::filter(const vector& ignore_patterns) + + bool + File::cmp_lt(const string& lhs, const string& rhs) { - entries.erase(remove_if(entries.begin(), entries.end(), FilterHelper(ignore_patterns)), - entries.end()); + const std::collate& c = std::use_facet>(std::locale()); + + return c.compare(lhs.c_str(), lhs.c_str() + lhs.length(), + rhs.c_str(), rhs.c_str() + rhs.length()) < 0; } - int - operator<(const File& a, const File& b) + bool + operator<(const File& lhs, const File& rhs) { - return a.getName() < b.getName(); + return File::cmp_lt(lhs.getName(), rhs.getName()); } @@ -110,16 +112,16 @@ namespace snapper bool - file_name_less(const File& file, const string& name) + operator<(const File& file, const string& name) { - return file.getName() < name; + return File::cmp_lt(file.getName(), name); } Files::iterator Files::find(const string& name) { - iterator ret = lower_bound(entries.begin(), entries.end(), name, file_name_less); + iterator ret = lower_bound(entries.begin(), entries.end(), name); return (ret != end() && ret->getName() == name) ? ret : end(); } @@ -127,7 +129,7 @@ namespace snapper Files::const_iterator Files::find(const string& name) const { - const_iterator ret = lower_bound(entries.begin(), entries.end(), name, file_name_less); + const_iterator ret = lower_bound(entries.begin(), entries.end(), name); return (ret != end() && ret->getName() == name) ? ret : end(); } diff --git a/snapper/File.h b/snapper/File.h index 4a7aee72..dba89da1 100644 --- a/snapper/File.h +++ b/snapper/File.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2011-2014] Novell, Inc. + * Copyright (c) [2011-2015] Novell, Inc. * * All Rights Reserved. * @@ -140,6 +140,9 @@ namespace snapper XAUndoStatistic getXAUndoStatistic() const; + // C++ locale aware less-than comparison + static bool cmp_lt(const string& lhs, const string& rhs); + private: bool createParentDirectories(const string& path) const; diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am index cfa2b171..a29ccd4b 100644 --- a/testsuite/Makefile.am +++ b/testsuite/Makefile.am @@ -7,7 +7,7 @@ AM_CPPFLAGS = -I$(top_srcdir) $(DBUS_CFLAGS) LDADD = ../snapper/libsnapper.la ../dbus/libdbus.la -lboost_unit_test_framework check_PROGRAMS = sysconfig-get1.test dirname1.test basename1.test \ - equal-date.test dbus-escape.test + equal-date.test dbus-escape.test cmp-lt.test TESTS = $(check_PROGRAMS) diff --git a/testsuite/cmp-lt.cc b/testsuite/cmp-lt.cc new file mode 100644 index 00000000..1858e2cb --- /dev/null +++ b/testsuite/cmp-lt.cc @@ -0,0 +1,71 @@ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE snapper + +#include +#include + +#include + +using namespace snapper; + + +namespace std +{ + std::ostream& + operator<<(std::ostream& s, const vector& v) + { + for(std::vector::const_iterator it = v.begin(); it != v.end(); ++it) + { + if (it != v.begin()) + s << " "; + s << *it; + } + + return s; + } +} + + +BOOST_AUTO_TEST_CASE(test1) +{ + std::locale::global(std::locale("C")); + + vector v = { "A", "B", "b", "a" }; + sort(v.begin(), v.end(), File::cmp_lt); + + BOOST_CHECK_EQUAL(v, vector({ "A", "B", "a", "b" })); +} + + +BOOST_AUTO_TEST_CASE(test2) +{ + std::locale::global(std::locale("en_US.UTF-8")); + + vector v = { "A", "B", "b", "a" }; + sort(v.begin(), v.end(), File::cmp_lt); + + BOOST_CHECK_EQUAL(v, vector({ "a", "A", "b", "B" })); +} + + +BOOST_AUTO_TEST_CASE(test3) +{ + std::locale::global(std::locale("de_DE.UTF-8")); + + vector v = { "a", "b", "ä" }; + sort(v.begin(), v.end(), File::cmp_lt); + + BOOST_CHECK_EQUAL(v, vector({ "a", "ä", "b" })); +} + + +BOOST_AUTO_TEST_CASE(test4) +{ + std::locale::global(std::locale("en_US.UTF-8")); + + vector v = { "a", "\344" }; // invalid UTF-8 + sort(v.begin(), v.end(), File::cmp_lt); + + BOOST_CHECK_EQUAL(v, vector({ "\344", "a" })); +}