[meld] Fix some handling of unicode file names (closes bgo#168760, bgo#694099)



commit 7a56fe43c241704813b2285a07f5d56b98162b23
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Sun Apr 7 06:26:06 2013 +1000

    Fix some handling of unicode file names (closes bgo#168760, bgo#694099)
    
    While in theory we should be using encoding from the file system, this
    turns out to usually be incorrect. Typically, the filenames we handle
    have already passed through GTK+ (and are thus UTF-8) or have come
    from Python, in which case if we pass unicode in, we get unicode out.
    
    This patch basically takes these two factors into account and tries
    to make sure we give Python's file system handling unicode objects and
    decodes the UTF-8 we get from GTK+. This appears to work on both
    Linux (which it already did, assuming a UTF-8 file system...) and on
    Windows (UTF-16, probably).

 meld/dirdiff.py    |   12 +++++++++++-
 meld/filediff.py   |   19 ++++++++++++-------
 meld/newdifftab.py |    1 +
 meld/tree.py       |    5 ++++-
 meld/vcview.py     |    2 +-
 5 files changed, 29 insertions(+), 10 deletions(-)
---
diff --git a/meld/dirdiff.py b/meld/dirdiff.py
index e5b022e..c6a5b69 100644
--- a/meld/dirdiff.py
+++ b/meld/dirdiff.py
@@ -24,6 +24,7 @@ import os
 import re
 import shutil
 import stat
+import sys
 import time
 
 import gtk
@@ -577,10 +578,18 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
 
     def on_fileentry_activate(self, entry):
         locs = [e.get_full_path() for e in self.fileentry[:self.num_panes]]
+        locs = [l.decode('utf8') for l in locs]
         self.set_locations(locs)
 
     def set_locations(self, locations):
         self.set_num_panes(len(locations))
+        # This is difficult to trigger, and to test. Most of the time here we
+        # will actually have had UTF-8 from GTK, which has been unicode-ed by
+        # the time we get this far. This is a fallback, and may be wrong!
+        for i, l in enumerate(locations):
+            if not isinstance(l, unicode):
+                locations[i] = l.decode(sys.getfilesystemencoding())
+        # TODO: Support for blank folder comparisons should probably look here
         locations = [os.path.abspath(l or ".") for l in locations]
         self.current_path = None
         self.model.clear()
@@ -666,7 +675,8 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
 
                 for e in entries:
                     try:
-                        e = e.decode('utf8')
+                        if not isinstance(e, unicode):
+                            e = e.decode('utf8')
                     except UnicodeDecodeError:
                         approximate_name = e.decode('utf8', 'replace')
                         encoding_errors.append((pane, approximate_name))
diff --git a/meld/filediff.py b/meld/filediff.py
index 49e2aa7..3b73530 100644
--- a/meld/filediff.py
+++ b/meld/filediff.py
@@ -992,13 +992,17 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
            If an element is None, the text of a pane is left as is.
         """
         self._disconnect_buffer_handlers()
-        for i,f in enumerate(files):
-            if f:
-                absfile = os.path.abspath(f)
-                self.fileentry[i].set_filename(absfile)
-                self.fileentry[i].prepend_history(absfile)
-                self.textbuffer[i].reset_buffer(absfile)
-                self.msgarea_mgr[i].clear()
+        for i, f in enumerate(files):
+            if not f:
+                continue
+            if not isinstance(f, unicode):
+                files[i] = f = f.decode('utf8')
+            absfile = os.path.abspath(f)
+            self.fileentry[i].set_filename(absfile)
+            self.fileentry[i].prepend_history(absfile)
+            self.textbuffer[i].reset_buffer(absfile)
+            self.msgarea_mgr[i].clear()
+
         self.recompute_label()
         self.textview[len(files) >= 2].grab_focus()
         self._connect_buffer_handlers()
@@ -1526,6 +1530,7 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
         if self.check_save_modified() != gtk.RESPONSE_CANCEL:
             entries = self.fileentry[:self.num_panes]
             paths = [e.get_full_path() for e in entries]
+            paths = [p.decode('utf8') for p in paths]
             self.set_files(paths)
         return True
 
diff --git a/meld/newdifftab.py b/meld/newdifftab.py
index 2e4efd3..a1f5ad1 100644
--- a/meld/newdifftab.py
+++ b/meld/newdifftab.py
@@ -109,6 +109,7 @@ class NewDiffTab(gobject.GObject, gnomeglade.Component):
         for chooser in type_choosers[self.diff_type][:num_paths]:
             gfile = chooser.get_file()
             path = gfile.get_path() if gfile else ""
+            path = path.decode('utf8')
             compare_paths.append(path)
 
         tab = self.diff_methods[self.diff_type](compare_paths)
diff --git a/meld/tree.py b/meld/tree.py
index dc8c0b9..2962908 100644
--- a/meld/tree.py
+++ b/meld/tree.py
@@ -104,7 +104,10 @@ class DiffTreeStore(gtk.TreeStore):
         return [self.value_path(it, i) for i in range(self.ntree)]
 
     def value_path(self, it, pane):
-        return self.get_value(it, self.column_index(COL_PATH, pane))
+        path = self.get_value(it, self.column_index(COL_PATH, pane))
+        if path is not None:
+            path = path.decode('utf8')
+        return path
 
     def column_index(self, col, pane):
         return self.ntree * col + pane
diff --git a/meld/vcview.py b/meld/vcview.py
index 89cf9ae..f0044e1 100644
--- a/meld/vcview.py
+++ b/meld/vcview.py
@@ -868,7 +868,7 @@ class VcView(melddoc.MeldDoc, gnomeglade.Component):
 
     def treeview_search_cb(self, model, column, key, it):
         """Callback function for searching in VcView treeview"""
-        path = model.get_value(it, tree.COL_PATH)
+        path = model.value_path(it, 0)
 
         # if query text contains slash, search in full path
         if key.find('/') >= 0:


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]