After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 757881 - gtk-3.18.3 breaks filediff
gtk-3.18.3 breaks filediff
Status: RESOLVED DUPLICATE of bug 757963
Product: meld
Classification: Other
Component: filediff
3.15.x
Other Linux
: Normal critical
: ---
Assigned To: meld-maint
meld-maint
Depends on:
Blocks:
 
 
Reported: 2015-11-10 13:20 UTC by arne
Modified: 2015-11-13 23:35 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description arne 2015-11-10 13:20:25 UTC
Using gtk-3.18.3 breaks filediff, because GtkSource.Buffer.get_iter_at_line() now returns the tuple (bool, Gtk.TextIter) and not simply the iterator anymore.
Comment 1 Vlad Frolov 2015-11-11 06:18:00 UTC
It affects me also on Arch Linux:


Traceback (most recent call last):
  • File "/usr/lib/python2.7/site-packages/meld/task.py", line 110 in iteration
    ret = next(task)
  • File "/usr/lib/python2.7/site-packages/meld/filediff.py", line 1202 in _set_files_internal
    for i in self._diff_files():
  • File "/usr/lib/python2.7/site-packages/meld/filediff.py", line 1159 in _diff_files
    while next(step) is None:
  • File "/usr/lib/python2.7/site-packages/meld/diffutil.py", line 466 in set_sequences_iter
    while next(work) is None:
  • File "/usr/lib/python2.7/site-packages/meld/matchers.py", line 246 in initialise
    a, b = self.preprocess()
  • File "/usr/lib/python2.7/site-packages/meld/matchers.py", line 155 in preprocess
    a, b = self.preprocess_remove_prefix_suffix(self.a, self.b)
  • File "/usr/lib/python2.7/site-packages/meld/matchers.py", line 109 in preprocess_remove_prefix_suffix
    self.common_prefix = find_common_prefix(a, b)
  • File "/usr/lib/python2.7/site-packages/meld/matchers.py", line 43 in find_common_prefix
    if a[0] == b[0]:
  • File "/usr/lib/python2.7/site-packages/meld/meldbuffer.py", line 268 in __getitem__
    line_end = line_start.copy()
AttributeError: 'tuple' object has no attribute 'copy'
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/meld/filediff.py", line 1775, in _sync_vscroll
    val, height = self.textview[i].get_line_yrange(it)
TypeError: argument iter: Expected Gtk.TextIter, but got tuple
Comment 2 David I. Lehn 2015-11-12 01:47:24 UTC
In case anyone comes across this issue and wants a temporary fix, here's a patch for MeldBuffer.  Works with 3.15.0 too.  I didn't look into the root cause of this so perhaps a gtk bug fix would be more appropriate.  I don't know.  But this will fix meld up to work if you happen to be using a distribution with gtk libs installed that expose this bug.

--- meld-3.14.1-orig/meld/meldbuffer.py 2015-10-02 22:10:11.000000000 -0400
+++ meld-3.14.1/meld/meldbuffer.py      2015-11-11 20:37:09.412543281 -0500
@@ -76,6 +76,9 @@
         self.data.filename = filename
         self.data.label = label
 
+    def get_iter_at_line(self, line):
+        return super(MeldBuffer, self).get_iter_at_line(line)[1]
+
     def get_iter_at_line_or_eof(self, line):
         """Return a Gtk.TextIter at the given line, or the end of the buffer.
Comment 3 rudygotya 2015-11-12 08:13:17 UTC
thank you very much for the patch - works for me.
Comment 4 arne 2015-11-12 10:12:39 UTC
(In reply to David I. Lehn from comment #2)
> In case anyone comes across this issue and wants a temporary fix, here's a
> patch for MeldBuffer.  Works with 3.15.0 too.  I didn't look into the root
> cause of this so perhaps a gtk bug fix would be more appropriate.  I don't
> know.  But this will fix meld up to work if you happen to be using a
> distribution with gtk libs installed that expose this bug.
> 
the root cause is this gtk patch where the get_iter_* now return gbooleans instead of void:

commit cf51c4f6dbd91dae1878a0cb0d08b24c67e15232
Author: Sébastien Wilmet <swilmet@gnome.org>
Date:   Thu Oct 15 10:43:10 2015 +0200

    textbuffer: nicer get_iter functions
    
    Avoid crashes when passing an invalid location to a
    gtk_text_buffer_get_iter_at_*() function.
    
    A boolean is returned to know if @iter has been set to the exact
    location.
    
    Unit tests are added.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=735341

diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c
index 1bf1b68..7295021 100644
--- a/gtk/gtktextbuffer.c
+++ b/gtk/gtktextbuffer.c
@@ -2862,22 +2862,48 @@ gtk_text_buffer_remove_all_tags (GtkTextBuffer     *buffer,
  * @line_number: line number counting from 0
  * @char_offset: char offset from start of line
  *
- * Obtains an iterator pointing to @char_offset within the given
- * line. The @char_offset must exist, offsets off the end of the line
- * are not allowed. Note characters, not bytes;
- * UTF-8 may encode one character as multiple bytes.
+ * Obtains an iterator pointing to @char_offset within the given line. Note
+ * characters, not bytes; UTF-8 may encode one character as multiple bytes.
+ *
+ * Before the 3.20 version, it was not allowed to pass an invalid location.
+ *
+ * Since the 3.20 version, if @line_number is greater than the number of lines
+ * in the @buffer, the end iterator is returned. And if @char_offset is off the
+ * end of the line, the iterator at the end of the line is returned.
+ *
+ * Returns: whether the exact position has been found (since 3.20).
  **/
-void
+gboolean
 gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer,
                                          GtkTextIter   *iter,
                                          gint           line_number,
                                          gint           char_offset)
 {
-  g_return_if_fail (iter != NULL);
-  g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+  GtkTextIter end_line_iter;
+
+  g_return_val_if_fail (iter != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
+
+  if (line_number >= gtk_text_buffer_get_line_count (buffer))
+    {
+      gtk_text_buffer_get_end_iter (buffer, iter);
+      return FALSE;
+    }
+
+  _gtk_text_btree_get_iter_at_line_char (get_btree (buffer), iter, line_number, 0);
 
-  _gtk_text_btree_get_iter_at_line_char (get_btree (buffer),
-                                         iter, line_number, char_offset);
+  end_line_iter = *iter;
+  if (!gtk_text_iter_ends_line (&end_line_iter))
+    gtk_text_iter_forward_to_line_end (&end_line_iter);
+
+  if (char_offset > gtk_text_iter_get_line_offset (&end_line_iter))
+    {
+      *iter = end_line_iter;
+      return FALSE;
+    }
+
+  gtk_text_iter_set_line_offset (iter, char_offset);
+  return TRUE;
 }
 
 /**
@@ -2888,21 +2914,48 @@ gtk_text_buffer_get_iter_at_line_offset (GtkTextBuffer *buffer,
  * @byte_index: byte index from start of line
  *
  * Obtains an iterator pointing to @byte_index within the given line.
- * @byte_index must be the start of a UTF-8 character, and must not be
- * beyond the end of the line.  Note bytes, not
+ * @byte_index must be the start of a UTF-8 character. Note bytes, not
  * characters; UTF-8 may encode one character as multiple bytes.
+ *
+ * Before the 3.20 version, it was not allowed to pass an invalid location.
+ *
+ * Since the 3.20 version, if @line_number is greater than the number of lines
+ * in the @buffer, the end iterator is returned. And if @byte_index is off the
+ * end of the line, the iterator at the end of the line is returned.
+ *
+ * Returns: whether the exact position has been found (since 3.20).
  **/
-void
+gboolean
 gtk_text_buffer_get_iter_at_line_index  (GtkTextBuffer *buffer,
                                          GtkTextIter   *iter,
                                          gint           line_number,
                                          gint           byte_index)
 {
-  g_return_if_fail (iter != NULL);
-  g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+  GtkTextIter end_line_iter;
+
+  g_return_val_if_fail (iter != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
+
+  if (line_number >= gtk_text_buffer_get_line_count (buffer))
+    {
+      gtk_text_buffer_get_end_iter (buffer, iter);
+      return FALSE;
+    }
+
+  gtk_text_buffer_get_iter_at_line (buffer, iter, line_number);
+
+  end_line_iter = *iter;
+  if (!gtk_text_iter_ends_line (&end_line_iter))
+    gtk_text_iter_forward_to_line_end (&end_line_iter);
 
-  _gtk_text_btree_get_iter_at_line_byte (get_btree (buffer),
-                                         iter, line_number, byte_index);
+  if (byte_index > gtk_text_iter_get_line_index (&end_line_iter))
+    {
+      *iter = end_line_iter;
+      return FALSE;
+    }
+
+  gtk_text_iter_set_line_index (iter, byte_index);
+  return TRUE;
 }
 
 /**
@@ -2913,16 +2966,18 @@ gtk_text_buffer_get_iter_at_line_index  (GtkTextBuffer *buffer,
  *
  * Initializes @iter to the start of the given line. If @line_number is greater
  * than the number of lines in the @buffer, the end iterator is returned.
+ *
+ * Returns: whether the exact position has been found (since 3.20).
  **/
-void
+gboolean
 gtk_text_buffer_get_iter_at_line (GtkTextBuffer *buffer,
                                   GtkTextIter   *iter,
                                   gint           line_number)
 {
-  g_return_if_fail (iter != NULL);
-  g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+  g_return_val_if_fail (iter != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE);
 
-  gtk_text_buffer_get_iter_at_line_offset (buffer, iter, line_number, 0);
+  return gtk_text_buffer_get_iter_at_line_offset (buffer, iter, line_number, 0);
 }
 
 /**
Comment 5 Kai Willadsen 2015-11-12 20:59:42 UTC
(In reply to arne from comment #4)
> (In reply to David I. Lehn from comment #2)
> > In case anyone comes across this issue and wants a temporary fix, here's a
> > patch for MeldBuffer.  Works with 3.15.0 too.  I didn't look into the root
> > cause of this so perhaps a gtk bug fix would be more appropriate.  I don't
> > know.  But this will fix meld up to work if you happen to be using a
> > distribution with gtk libs installed that expose this bug.
> > 
> the root cause is this gtk patch where the get_iter_* now return gbooleans
> instead of void:
> 
> commit cf51c4f6dbd91dae1878a0cb0d08b24c67e15232
> Author: Sébastien Wilmet <swilmet@gnome.org>
> Date:   Thu Oct 15 10:43:10 2015 +0200

Thanks for chasing that down. This is a great situation where there's no C API break, but there *is* a Python-level API break

in a micro release.


The 'real' 'fix' will be approximately what was posted in comment 2, but with an isinstance check or something similarly terrible.
Comment 6 Jan Alexander Steffens (heftig) 2015-11-12 21:00:43 UTC
Gtk+ 3.18.4 reverted the API change; you can close this as a duplicate of bug #757963.
Comment 7 Kai Willadsen 2015-11-13 23:35:36 UTC
(In reply to Jan Alexander Steffens (heftig) from comment #6)
> Gtk+ 3.18.4 reverted the API change; you can close this as a duplicate of
> bug #757963.

Thanks, that's very helpful. Since it was only in a single micro release, I'm not going to add a workaround here.

*** This bug has been marked as a duplicate of bug 757963 ***