[gitg] Improve support for binary file detection in diff views



commit 411c5743ce3e4f4aec6ec517738062a7a5de44e3
Author: Jesse van den Kieboom <jessevdk gnome org>
Date:   Tue Aug 16 17:59:27 2016 +0200

    Improve support for binary file detection in diff views
    
    https://bugzilla.gnome.org/show_bug.cgi?id=768650

 configure.ac                                       |    2 +-
 libgitg/Makefile.am                                |   82 +++++++------
 libgitg/gitg-diff-view-file-info.vala              |  104 ++++++++++++++++
 libgitg/gitg-diff-view-file-renderer-binary.vala   |   28 +++++
 libgitg/gitg-diff-view-file-renderer-text.vala     |  127 ++++++++++++++------
 libgitg/gitg-diff-view-file.vala                   |   11 ++-
 libgitg/gitg-diff-view.vala                        |  114 ++++++++++++++++--
 libgitg/resources/resources.xml                    |    1 +
 .../ui/gitg-diff-view-file-renderer-binary.ui      |   22 ++++
 libgitg/resources/ui/gitg-diff-view-file.ui        |    2 +
 po/POTFILES.in                                     |    1 +
 11 files changed, 405 insertions(+), 89 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index ba45b40..e956481 100644
--- a/configure.ac
+++ b/configure.ac
@@ -132,7 +132,7 @@ GLIB_REQUIRED_VERSION=2.38
 GTK_REQUIRED_VERSION=3.20.0
 GTKSOURCEVIEW_REQUIRED_VERSION=3.10
 INTROSPECTION_REQUIRED=0.10.1
-LIBGIT2_GLIB_REQUIRED_VERSION=0.24.0
+LIBGIT2_GLIB_REQUIRED_VERSION=0.24.1
 LIBGIT2_GLIB_REQUIRED_MAX_VERSION=0.25.0
 LIBXML_REQUIRED_VERSION=2.9.0
 
diff --git a/libgitg/Makefile.am b/libgitg/Makefile.am
index 8262f0e..245d103 100644
--- a/libgitg/Makefile.am
+++ b/libgitg/Makefile.am
@@ -52,46 +52,48 @@ libgitg_libgitg_1_0_la_VALAFLAGS =  \
        --header libgitg/libgitg.h      \
        --gresources "$(top_srcdir)/libgitg/resources/resources.xml"
 
-libgitg_libgitg_1_0_la_VALASOURCES =                   \
-       libgitg/gitg-assembly-info.vala                 \
-       libgitg/gitg-async.vala                         \
-       libgitg/gitg-authentication-dialog.vala         \
-       libgitg/gitg-avatar-cache.vala                  \
-       libgitg/gitg-branch-base.vala                   \
-       libgitg/gitg-branch.vala                        \
-       libgitg/gitg-cell-renderer-lanes.vala           \
-       libgitg/gitg-color.vala                         \
-       libgitg/gitg-commit-list-view.vala              \
-       libgitg/gitg-commit-model.vala                  \
-       libgitg/gitg-commit.vala                        \
-       libgitg/gitg-credentials-manager.vala           \
-       libgitg/gitg-date.vala                          \
-       libgitg/gitg-diff-stat.vala                     \
-       libgitg/gitg-diff-view.vala                     \
-       libgitg/gitg-diff-view-file.vala                \
-       libgitg/gitg-diff-view-file-selectable.vala     \
-       libgitg/gitg-diff-view-file-renderer.vala       \
-       libgitg/gitg-diff-view-file-renderer-text.vala  \
-       libgitg/gitg-diff-view-lines-renderer.vala      \
-       libgitg/gitg-diff-selectable.vala               \
-       libgitg/gitg-diff-view-commit-details.vala      \
-       libgitg/gitg-diff-view-options.vala             \
-       libgitg/gitg-hook.vala                          \
-       libgitg/gitg-init.vala                          \
-       libgitg/gitg-label-renderer.vala                \
-       libgitg/gitg-lane.vala                          \
-       libgitg/gitg-lanes.vala                         \
-       libgitg/gitg-progress-bin.vala                  \
-       libgitg/gitg-ref-base.vala                      \
-       libgitg/gitg-ref.vala                           \
-       libgitg/gitg-remote.vala                        \
-       libgitg/gitg-repository-list-box.vala           \
-       libgitg/gitg-repository.vala                    \
-       libgitg/gitg-resource.vala                      \
-       libgitg/gitg-sidebar.vala                       \
-       libgitg/gitg-stage-status-enumerator.vala       \
-       libgitg/gitg-stage.vala                         \
-       libgitg/gitg-utils.vala                         \
+libgitg_libgitg_1_0_la_VALASOURCES =                           \
+       libgitg/gitg-assembly-info.vala                         \
+       libgitg/gitg-async.vala                                 \
+       libgitg/gitg-authentication-dialog.vala                 \
+       libgitg/gitg-avatar-cache.vala                          \
+       libgitg/gitg-branch-base.vala                           \
+       libgitg/gitg-branch.vala                                \
+       libgitg/gitg-cell-renderer-lanes.vala                   \
+       libgitg/gitg-color.vala                                 \
+       libgitg/gitg-commit-list-view.vala                      \
+       libgitg/gitg-commit-model.vala                          \
+       libgitg/gitg-commit.vala                                \
+       libgitg/gitg-credentials-manager.vala                   \
+       libgitg/gitg-date.vala                                  \
+       libgitg/gitg-diff-stat.vala                             \
+       libgitg/gitg-diff-view.vala                             \
+       libgitg/gitg-diff-view-file.vala                        \
+       libgitg/gitg-diff-view-file-info.vala                   \
+       libgitg/gitg-diff-view-file-selectable.vala             \
+       libgitg/gitg-diff-view-file-renderer.vala               \
+       libgitg/gitg-diff-view-file-renderer-binary.vala        \
+       libgitg/gitg-diff-view-file-renderer-text.vala          \
+       libgitg/gitg-diff-view-lines-renderer.vala              \
+       libgitg/gitg-diff-selectable.vala                       \
+       libgitg/gitg-diff-view-commit-details.vala              \
+       libgitg/gitg-diff-view-options.vala                     \
+       libgitg/gitg-hook.vala                                  \
+       libgitg/gitg-init.vala                                  \
+       libgitg/gitg-label-renderer.vala                        \
+       libgitg/gitg-lane.vala                                  \
+       libgitg/gitg-lanes.vala                                 \
+       libgitg/gitg-progress-bin.vala                          \
+       libgitg/gitg-ref-base.vala                              \
+       libgitg/gitg-ref.vala                                   \
+       libgitg/gitg-remote.vala                                \
+       libgitg/gitg-repository-list-box.vala                   \
+       libgitg/gitg-repository.vala                            \
+       libgitg/gitg-resource.vala                              \
+       libgitg/gitg-sidebar.vala                               \
+       libgitg/gitg-stage-status-enumerator.vala               \
+       libgitg/gitg-stage.vala                                 \
+       libgitg/gitg-utils.vala                                 \
        libgitg/gitg-when-mapped.vala
 
 libgitg_libgitg_1_0_la_SOURCES =                               \
diff --git a/libgitg/gitg-diff-view-file-info.vala b/libgitg/gitg-diff-view-file-info.vala
new file mode 100644
index 0000000..ac87b8c
--- /dev/null
+++ b/libgitg/gitg-diff-view-file-info.vala
@@ -0,0 +1,104 @@
+class Gitg.DiffViewFileInfo : Object
+{
+       public Ggit.DiffDelta delta { get; construct set; }
+       public bool from_workdir { get; construct set; }
+       public Repository repository { get; construct set; }
+
+       public InputStream? new_file_input_stream { get; set; }
+       public string? new_file_content_type { get; private set; }
+
+       public DiffViewFileInfo(Repository repository, Ggit.DiffDelta delta, bool from_workdir)
+       {
+               Object(repository: repository, delta: delta, from_workdir: from_workdir);
+       }
+
+       public async void query(Cancellable? cancellable)
+       {
+               yield query_content(cancellable);
+       }
+
+       private async void query_content(Cancellable? cancellable)
+       {
+               var file = delta.get_new_file();
+               var id = file.get_oid();
+               var path = file.get_path();
+
+               if ((id.is_zero() && !from_workdir) || (path == null && from_workdir))
+               {
+                       return;
+               }
+
+               var location = repository.get_workdir().get_child(path);
+
+               if (!from_workdir)
+               {
+                       Ggit.Blob blob;
+
+                       try
+                       {
+                               blob = repository.lookup<Ggit.Blob>(id);
+                       }
+                       catch (Error e)
+                       {
+                               return;
+                       }
+
+                       var bytes = new Bytes(blob.get_raw_content());
+                       new_file_input_stream = new GLib.MemoryInputStream.from_bytes(bytes);
+               }
+               else
+               {
+                       // Try to read from disk
+                       try
+                       {
+                               new_file_input_stream = yield location.read_async(Priority.DEFAULT, 
cancellable);
+                       }
+                       catch
+                       {
+                               return;
+                       }
+               }
+
+               var seekable = new_file_input_stream as Seekable;
+
+               if (seekable != null && seekable.can_seek())
+               {
+                       // Read a little bit of content to guess the type
+                       yield guess_content_type(new_file_input_stream, location.get_basename(), cancellable);
+
+                       try
+                       {
+                               seekable.seek(0, SeekType.SET, cancellable);
+                       }
+                       catch (Error e)
+                       {
+                               stderr.printf("Failed to seek back to beginning of stream...\n");
+                               new_file_input_stream = null;
+                       }
+               }
+       }
+
+       private async void guess_content_type(InputStream stream, string basename, Cancellable? cancellable)
+       {
+               var buffer = new uint8[4096];
+               size_t bytes_read = 0;
+
+               try
+               {
+                       yield stream.read_all_async(buffer, Priority.DEFAULT, cancellable, out bytes_read);
+               }
+               catch (Error e)
+               {
+                       if (bytes_read <= 0)
+                       {
+                               return;
+                       }
+               }
+
+               buffer.length = (int)bytes_read;
+
+               bool uncertain;
+               new_file_content_type = GLib.ContentType.guess(basename, buffer, out uncertain);
+
+       }
+}
\ No newline at end of file
diff --git a/libgitg/gitg-diff-view-file-renderer-binary.vala 
b/libgitg/gitg-diff-view-file-renderer-binary.vala
new file mode 100644
index 0000000..ed020b4
--- /dev/null
+++ b/libgitg/gitg-diff-view-file-renderer-binary.vala
@@ -0,0 +1,28 @@
+/*
+ * This file is part of gitg
+ *
+ * Copyright (C) 2016 - Jesse van den Kieboom
+ *
+ * gitg is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gitg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gitg. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+[GtkTemplate (ui = "/org/gnome/gitg/ui/gitg-diff-view-file-renderer-binary.ui")]
+class Gitg.DiffViewFileRendererBinary : Gtk.Grid, DiffViewFileRenderer
+{
+       public void add_hunk(Ggit.DiffHunk hunk, Gee.ArrayList<Ggit.DiffLine> lines)
+       {
+       }
+}
+
+// ex:ts=4 noet
diff --git a/libgitg/gitg-diff-view-file-renderer-text.vala b/libgitg/gitg-diff-view-file-renderer-text.vala
index b6fc537..576b181 100644
--- a/libgitg/gitg-diff-view-file-renderer-text.vala
+++ b/libgitg/gitg-diff-view-file-renderer-text.vala
@@ -83,8 +83,18 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
        }
 
        public int maxlines { get; set; }
-       public Ggit.DiffDelta? delta { get; construct set; }
-       public Repository? repository { get; construct set; }
+
+       public DiffViewFileInfo info { get; construct set; }
+
+       public Ggit.DiffDelta? delta
+       {
+               get { return info.delta; }
+       }
+
+       public Repository? repository
+       {
+               get { return info.repository; }
+       }
 
        public bool highlight
        {
@@ -92,8 +102,11 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
 
                construct set
                {
-                       d_highlight = value;
-                       update_highlight();
+                       if (d_highlight != value)
+                       {
+                               d_highlight = value;
+                               update_highlight();
+                       }
                }
 
                default = true;
@@ -155,9 +168,9 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
                }
        }
 
-       public DiffViewFileRendererText(Repository? repository, Ggit.DiffDelta delta, bool new_is_workdir, 
bool can_select)
+       public DiffViewFileRendererText(DiffViewFileInfo info, bool can_select)
        {
-               Object(repository: repository, new_is_workdir: new_is_workdir, delta: delta, can_select: 
can_select);
+               Object(info: info, can_select: can_select);
        }
 
        construct
@@ -234,32 +247,73 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
                        var cancellable = new Cancellable();
                        d_higlight_cancellable = cancellable;
 
-                       init_highlighting_buffer.begin(delta.get_old_file(), false, cancellable, (obj, res) 
=> {
-                               var buffer = init_highlighting_buffer.end(res);
-
-                               if (!cancellable.is_cancelled())
-                               {
-                                       d_old_highlight_buffer = buffer;
-                                       d_old_highlight_ready = true;
+                       init_highlighting_buffer_old.begin(cancellable, (obj, res) => {
+                               init_highlighting_buffer_old.end(res);
+                       });
 
-                                       update_highlighting_ready();
-                               }
+                       init_highlighting_buffer_new.begin(cancellable, (obj, res) => {
+                               init_highlighting_buffer_new.end(res);
                        });
+               }
+               else
+               {
+                       update_highlighting_ready();
+               }
+       }
 
-                       init_highlighting_buffer.begin(delta.get_new_file(), new_is_workdir, cancellable, 
(obj, res) => {
-                               var buffer = init_highlighting_buffer.end(res);
+       private async void init_highlighting_buffer_old(Cancellable cancellable)
+       {
+               var buffer = yield init_highlighting_buffer(delta.get_old_file(), false, cancellable);
 
-                               if (!cancellable.is_cancelled())
-                               {
-                                       d_new_highlight_buffer = buffer;
-                                       d_new_highlight_ready = true;
+               if (!cancellable.is_cancelled())
+               {
+                       d_old_highlight_buffer = buffer;
+                       d_old_highlight_ready = true;
 
-                                       update_highlighting_ready();
-                               }
-                       });
+                       update_highlighting_ready();
+               }
+       }
+
+       private File? get_file_location(Ggit.DiffFile file)
+       {
+               var path = file.get_path();
+
+               if (path == null)
+               {
+                       return null;
+               }
+
+               return repository.get_workdir().get_child(path);
+       }
+
+       private async void init_highlighting_buffer_new(Cancellable cancellable)
+       {
+               Gtk.SourceBuffer? buffer;
+
+               var file = delta.get_new_file();
+
+               if (info.new_file_input_stream != null)
+               {
+                       // Use once
+                       var stream = info.new_file_input_stream;
+                       info.new_file_input_stream = null;
+
+                       buffer = yield init_highlighting_buffer_from_stream(delta.get_new_file(),
+                                                                           get_file_location(file),
+                                                                           stream,
+                                                                           info.new_file_content_type,
+                                                                           cancellable);
                }
                else
                {
+                       buffer = yield init_highlighting_buffer(delta.get_new_file(), info.from_workdir, 
cancellable);
+               }
+
+               if (!cancellable.is_cancelled())
+               {
+                       d_new_highlight_buffer = buffer;
+                       d_new_highlight_ready = true;
+
                        update_highlighting_ready();
                }
        }
@@ -267,17 +321,13 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
        private async Gtk.SourceBuffer? init_highlighting_buffer(Ggit.DiffFile file, bool from_workdir, 
Cancellable cancellable)
        {
                var id = file.get_oid();
-               var path = file.get_path();
+               var location = get_file_location(file);
 
-               if ((id.is_zero() && !from_workdir) || (path == null && from_workdir))
+               if ((id.is_zero() && !from_workdir) || (location == null && from_workdir))
                {
                        return null;
                }
 
-               var sfile = new Gtk.SourceFile();
-               sfile.location = repository.get_workdir().get_child(path);
-
-               var basename = sfile.location.get_basename();
                uint8[] content;
 
                if (!from_workdir)
@@ -304,7 +354,7 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
 
                                // Read it all into a buffer so we can guess the content type from
                                // it. This isn't really nice, but it's simple.
-                               yield sfile.location.load_contents_async(cancellable, out content, out etag);
+                               yield location.load_contents_async(cancellable, out content, out etag);
                        }
                        catch
                        {
@@ -313,13 +363,17 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
                }
 
                bool uncertain;
-               var content_type = GLib.ContentType.guess(basename, content, out uncertain);
+               var content_type = GLib.ContentType.guess(location.get_basename(), content, out uncertain);
+
+               var stream = new GLib.MemoryInputStream.from_bytes(new Bytes(content));
 
-               var bytes = new Bytes(content);
-               var stream = new GLib.MemoryInputStream.from_bytes(bytes);
+               return yield init_highlighting_buffer_from_stream(file, location, stream, content_type, 
cancellable);
+       }
 
+       private async Gtk.SourceBuffer? init_highlighting_buffer_from_stream(Ggit.DiffFile file, File 
location, InputStream stream, string content_type, Cancellable cancellable)
+       {
                var manager = Gtk.SourceLanguageManager.get_default();
-               var language = manager.guess_language(basename, content_type);
+               var language = manager.guess_language(location.get_basename(), content_type);
 
                if (language == null)
                {
@@ -334,6 +388,9 @@ class Gitg.DiffViewFileRendererText : Gtk.SourceView, DiffSelectable, DiffViewFi
                buffer.highlight_syntax = true;
                buffer.style_scheme = style_scheme_manager.get_scheme("classic");
 
+               var sfile = new Gtk.SourceFile();
+               sfile.location = location;
+
                var loader = new Gtk.SourceFileLoader.from_stream(buffer, sfile, stream);
 
                try
diff --git a/libgitg/gitg-diff-view-file.vala b/libgitg/gitg-diff-view-file.vala
index 759e10d..63bcc35 100644
--- a/libgitg/gitg-diff-view-file.vala
+++ b/libgitg/gitg-diff-view-file.vala
@@ -104,11 +104,11 @@ class Gitg.DiffViewFile : Gtk.Grid
                Object(repository: repository, delta: delta);
        }
 
-       public DiffViewFile.text(Repository? repository, Ggit.DiffDelta delta, bool new_is_workdir, bool 
handle_selection)
+       public DiffViewFile.text(DiffViewFileInfo info, bool handle_selection)
        {
-               this(repository, delta);
+               this(info.repository, info.delta);
 
-               this.renderer = new DiffViewFileRendererText(repository, delta, new_is_workdir, 
handle_selection);
+               this.renderer = new DiffViewFileRendererText(info, handle_selection);
                this.renderer.show();
 
                this.renderer.bind_property("added", d_diff_stat_file, "added");
@@ -118,6 +118,11 @@ class Gitg.DiffViewFile : Gtk.Grid
        public DiffViewFile.binary(Repository? repository, Ggit.DiffDelta delta)
        {
                this(repository, delta);
+
+               this.renderer = new DiffViewFileRendererBinary();
+               this.renderer.show();
+
+               d_diff_stat_file.hide();
        }
 
        public DiffViewFile.image(Repository? repository, Ggit.DiffDelta delta)
diff --git a/libgitg/gitg-diff-view.vala b/libgitg/gitg-diff-view.vala
index 47f4185..4412676 100644
--- a/libgitg/gitg-diff-view.vala
+++ b/libgitg/gitg-diff-view.vala
@@ -265,8 +265,6 @@ public class Gitg.DiffView : Gtk.Grid
                }
        }
 
-       private delegate void Anon();
-
        private void auto_change_expanded(bool expanded)
        {
                SignalHandler.block(d_commit_details, d_expanded_notify);
@@ -307,13 +305,74 @@ public class Gitg.DiffView : Gtk.Grid
                return path;
        }
 
+       private delegate void Anon();
+
+       private string key_for_delta(Ggit.DiffDelta delta)
+       {
+               var new_file = delta.get_new_file();
+               var new_path = new_file.get_path();
+
+               if (new_path != null)
+               {
+                       return @"path:$(new_path)";
+               }
+
+               var old_file = delta.get_old_file();
+               var old_path = old_file.get_path();
+
+               if (old_path != null)
+               {
+                       return @"path:$(old_path)";
+               }
+
+               return "";
+       }
+
        private void update_diff(Ggit.Diff diff, bool preserve_expanded, Cancellable? cancellable)
        {
+               var nqueries = 0;
+               var finished = false;
+               var infomap = new Gee.HashMap<string, DiffViewFileInfo>();
+
+               Anon check_finish = () => {
+                       if (nqueries == 0 && finished && (cancellable == null || !cancellable.is_cancelled()))
+                       {
+                               finished = false;
+                               update_diff_hunks(diff, preserve_expanded, infomap, cancellable);
+                       }
+               };
+
+               // Collect file info asynchronously first
+               for (var i = 0; i < diff.get_num_deltas(); i++)
+               {
+                       var delta = diff.get_delta(i);
+                       var info = new DiffViewFileInfo(repository, delta, new_is_workdir);
+
+                       nqueries++;
+
+                       info.query.begin(cancellable, (obj, res) => {
+                               info.query.end(res);
+
+                               infomap[key_for_delta(delta)] = info;
+
+                               nqueries--;
+
+                               check_finish();
+                       });
+               }
+
+               finished = true;
+               check_finish();
+       }
+
+       private void update_diff_hunks(Ggit.Diff diff, bool preserve_expanded, Gee.HashMap<string, 
DiffViewFileInfo> infomap, Cancellable? cancellable)
+       {
                var files = new Gee.ArrayList<Gitg.DiffViewFile>();
 
                Gitg.DiffViewFile? current_file = null;
                Ggit.DiffHunk? current_hunk = null;
                Gee.ArrayList<Ggit.DiffLine>? current_lines = null;
+               var current_is_binary = false;
 
                var maxlines = 0;
 
@@ -352,8 +411,40 @@ public class Gitg.DiffView : Gtk.Grid
 
                                        add_file();
 
-                                       current_file = new Gitg.DiffViewFile.text(repository, delta, 
new_is_workdir, handle_selection);
-                                       this.bind_property("highlight", current_file.renderer, "highlight", 
BindingFlags.SYNC_CREATE);
+                                       DiffViewFileInfo? info = null;
+                                       var deltakey = key_for_delta(delta);
+
+                                       if (infomap.has_key(deltakey))
+                                       {
+                                               info = infomap[deltakey];
+                                       }
+                                       else
+                                       {
+                                               info = new DiffViewFileInfo(repository, delta, 
new_is_workdir);
+                                       }
+
+                                       current_is_binary = ((delta.get_flags() & Ggit.DiffFlag.BINARY) != 0);
+
+                                       // List of known binary file types that may be wrongly classified by
+                                       // libgit2 because it does not contain any null bytes in the first N
+                                       // bytes. E.g. PDF
+                                       var known_binary_files_types = new string[] {"application/pdf"};
+
+                                       // Ignore binary based on content type
+                                       if (info != null && info.new_file_content_type in 
known_binary_files_types)
+                                       {
+                                               current_is_binary = true;
+                                       }
+
+                                       if (current_is_binary)
+                                       {
+                                               current_file = new Gitg.DiffViewFile.binary(repository, 
delta);
+                                       }
+                                       else
+                                       {
+                                               current_file = new Gitg.DiffViewFile.text(info, 
handle_selection);
+                                               this.bind_property("highlight", current_file.renderer, 
"highlight", BindingFlags.SYNC_CREATE);
+                                       }
 
                                        return 0;
                                },
@@ -374,13 +465,16 @@ public class Gitg.DiffView : Gtk.Grid
                                                return 1;
                                        }
 
-                                       maxlines = int.max(maxlines, hunk.get_old_start() + 
hunk.get_old_lines());
-                                       maxlines = int.max(maxlines, hunk.get_new_start() + 
hunk.get_new_lines());
+                                       if (!current_is_binary)
+                                       {
+                                               maxlines = int.max(maxlines, hunk.get_old_start() + 
hunk.get_old_lines());
+                                               maxlines = int.max(maxlines, hunk.get_new_start() + 
hunk.get_new_lines());
 
-                                       add_hunk();
+                                               add_hunk();
 
-                                       current_hunk = hunk;
-                                       current_lines = new Gee.ArrayList<Ggit.DiffLine>();
+                                               current_hunk = hunk;
+                                               current_lines = new Gee.ArrayList<Ggit.DiffLine>();
+                                       }
 
                                        return 0;
                                },
@@ -391,7 +485,7 @@ public class Gitg.DiffView : Gtk.Grid
                                                return 1;
                                        }
 
-                                       if ((delta.get_flags() & Ggit.DiffFlag.BINARY) == 0)
+                                       if (!current_is_binary)
                                        {
                                                current_lines.add(line);
                                        }
diff --git a/libgitg/resources/resources.xml b/libgitg/resources/resources.xml
index f197fce..3b75da3 100644
--- a/libgitg/resources/resources.xml
+++ b/libgitg/resources/resources.xml
@@ -6,6 +6,7 @@
     <file compressed="true" preprocess="xml-stripblanks">ui/gitg-diff-view.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/gitg-diff-view-file.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/gitg-diff-view-file-renderer-text.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks">ui/gitg-diff-view-file-renderer-binary.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/gitg-diff-view-options.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/gitg-diff-view-options-spacing.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/gitg-diff-view-commit-details.ui</file>
diff --git a/libgitg/resources/ui/gitg-diff-view-file-renderer-binary.ui 
b/libgitg/resources/ui/gitg-diff-view-file-renderer-binary.ui
new file mode 100644
index 0000000..8be4f05
--- /dev/null
+++ b/libgitg/resources/ui/gitg-diff-view-file-renderer-binary.ui
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.19.0 -->
+<interface>
+  <requires lib="gtk+" version="3.16"/>
+  <template class="GitgDiffViewFileRendererBinary" parent="GtkGrid">
+    <property name="visible">True</property>
+    <child>
+      <object class="GtkLabel">
+        <property name="visible">True</property>
+        <property name="label" translatable="yes">Unable to display changes for binary file</property>
+        <property name="margin-top">3</property>
+        <property name="margin-start">12</property>
+        <property name="margin-end">12</property>
+        <property name="margin-bottom">9</property>
+        <property name="sensitive">False</property>
+        <attributes>
+          <attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
+        </attributes>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/libgitg/resources/ui/gitg-diff-view-file.ui b/libgitg/resources/ui/gitg-diff-view-file.ui
index b3b6284..a55a7c5 100644
--- a/libgitg/resources/ui/gitg-diff-view-file.ui
+++ b/libgitg/resources/ui/gitg-diff-view-file.ui
@@ -44,6 +44,8 @@
                 <property name="hexpand">True</property>
                 <property name="label">the/file/header</property>
                 <property name="halign">start</property>
+                <property name="margin_top">6</property>
+                <property name="margin_bottom">6</property>
               </object>
             </child>
           </object>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 7b6d601..66d056c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -62,6 +62,7 @@ plugins/files/gitg-files.vala
 [type: gettext/glade]gitg/resources/ui/gitg-window.ui
 [type: gettext/glade]libgitg/resources/ui/gitg-authentication-dialog.ui
 [type: gettext/glade]libgitg/resources/ui/gitg-diff-view-commit-details.ui
+[type: gettext/glade]libgitg/resources/ui/gitg-diff-view-file-renderer-binary.ui
 [type: gettext/glade]libgitg/resources/ui/gitg-diff-view-options-spacing.ui
 [type: gettext/glade]libgitg/resources/ui/gitg-diff-view-options.ui
 [type: gettext/glade]libgitg/resources/ui/gitg-repository-list-box-row.ui


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