]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- sort files according to locale
authorArvin Schnell <aschnell@suse.de>
Wed, 15 Apr 2015 09:28:16 +0000 (11:28 +0200)
committerArvin Schnell <aschnell@suse.de>
Wed, 15 Apr 2015 09:28:16 +0000 (11:28 +0200)
LIBVERSION
client/commands.cc
client/snapper.cc
package/snapper.changes
snapper/File.cc
snapper/File.h
testsuite/Makefile.am
testsuite/cmp-lt.cc [new file with mode: 0644]

index 4a36342fcab700951adb18ae7adc930997f6c3f4..fd2a01863fdd3035fac5918c59666363544bfe23 100644 (file)
@@ -1 +1 @@
-3.0.0
+3.1.0
index 6cb865d4370c39c84d25f2f2e572c64072e08743..c046ab172c8e17c4e0238d9eff6e302102a97b3a 100644 (file)
@@ -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<XFile>
 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;
 }
 
index a34dfc306291d4991f1a59ffed547b29fcd94bed..47b823685600a3d6863c15dfcd23931a0a2985e9 100644 (file)
@@ -1553,7 +1553,7 @@ help(const list<Cmd>& cmds)
 int
 main(int argc, char** argv)
 {
-    setlocale(LC_ALL, "");
+    locale::global(locale(""));
 
     setLogDo(&log_do);
     setLogQuery(&log_query);
index ff7da09dacec8f6ff7421c76e9490d07f6d9725c..67bef5c6f7f1fa88e33e8bcc00f7c86c5ad21432 100644 (file)
@@ -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
 
index d62754ebcba9ab793b07c52bc71cd10be4e7c080..17a4aab42732806617f8b25356b04f2e189b8268 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) [2011-2014] Novell, Inc.
+ * Copyright (c) [2011-2015] Novell, Inc.
  *
  * All Rights Reserved.
  *
@@ -29,6 +29,7 @@
 #include <fnmatch.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <locale>
 #include <boost/algorithm/string.hpp>
 
 #include "snapper/File.h"
@@ -72,33 +73,34 @@ namespace snapper
     }
 
 
-    struct FilterHelper
+    void
+    Files::filter(const vector<string>& ignore_patterns)
     {
-       FilterHelper(const vector<string>& patterns)
-           : patterns(patterns) {}
-       bool operator()(const File& file)
-           {
-               for (vector<string>::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<string>& patterns;
-    };
+       std::function<bool(const File&)> 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<string>& 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<char>& c = std::use_facet<std::collate<char>>(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();
     }
 
index 4a7aee728dfb73885eda4b47c227d9ac5a529d1c..dba89da11166faf7bd740c240dc3b491350c1b46 100644 (file)
@@ -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;
index cfa2b1710e01931f8f0b86eb659d170ec699a508..a29ccd4b7a0b0d68b3634aa49ce454578a05bfd4 100644 (file)
@@ -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 (file)
index 0000000..1858e2c
--- /dev/null
@@ -0,0 +1,71 @@
+
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE snapper
+
+#include <locale>
+#include <boost/test/unit_test.hpp>
+
+#include <snapper/File.h>
+
+using namespace snapper;
+
+
+namespace std
+{
+    std::ostream&
+    operator<<(std::ostream& s, const vector<string>& v)
+    {
+       for(std::vector<string>::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<string> v = { "A", "B", "b", "a" };
+    sort(v.begin(), v.end(), File::cmp_lt);
+
+    BOOST_CHECK_EQUAL(v, vector<string>({ "A", "B", "a", "b" }));
+}
+
+
+BOOST_AUTO_TEST_CASE(test2)
+{
+    std::locale::global(std::locale("en_US.UTF-8"));
+
+    vector<string> v = { "A", "B", "b", "a" };
+    sort(v.begin(), v.end(), File::cmp_lt);
+
+    BOOST_CHECK_EQUAL(v, vector<string>({ "a", "A", "b", "B" }));
+}
+
+
+BOOST_AUTO_TEST_CASE(test3)
+{
+    std::locale::global(std::locale("de_DE.UTF-8"));
+
+    vector<string> v = { "a", "b", "ä" };
+    sort(v.begin(), v.end(), File::cmp_lt);
+
+    BOOST_CHECK_EQUAL(v, vector<string>({ "a", "ä", "b" }));
+}
+
+
+BOOST_AUTO_TEST_CASE(test4)
+{
+    std::locale::global(std::locale("en_US.UTF-8"));
+
+    vector<string> v = { "a", "\344" }; // invalid UTF-8
+    sort(v.begin(), v.end(), File::cmp_lt);
+
+    BOOST_CHECK_EQUAL(v, vector<string>({ "\344", "a" }));
+}