From 0a0dbcc22a6ecf4d3275840041247b05583ee113 Mon Sep 17 00:00:00 2001
From: DeathAxe <deathaxe@web.de>
Date: Wed, 23 Nov 2016 17:52:38 +0100
Subject: [PATCH] Show markers on new, ignored and untracked files only, if
 show_markers_on_untracked_file is true.

By now GitGutter shows '+' markers on each line for any file within a git repository even with `show_markers_on_untracked_file: false`.
But the documentation of this setting quite clearly says: "GitGutter shows icons for new files and ignored files."
This commit is to satisfy this description.

Result:

`show_markers_on_untracked_file: false`
	-> do not show any marker on ignored, untracked or new files.

`show_markers_on_untracked_file: true` (Default)
	-> show '*' for untracked files
	-> show 'x' for ignored files
	-> show '+' for new files# Please enter the commit message for your changes. Lines starting
---
 GitGutter.sublime-settings |  2 +-
 git_gutter_handler.py      | 10 ++++++
 git_gutter_popup.py        | 10 +++---
 git_gutter_show_diff.py    | 73 +++++++++++++++++---------------------
 4 files changed, 48 insertions(+), 47 deletions(-)

diff --git a/GitGutter.sublime-settings b/GitGutter.sublime-settings
index 91d186d6..27401499 100644
--- a/GitGutter.sublime-settings
+++ b/GitGutter.sublime-settings
@@ -57,7 +57,7 @@
   "ignore_whitespace": "none",
 
   // Add a special marker on untracked files
-  "show_markers_on_untracked_file": false,
+  "show_markers_on_untracked_file": true,
 
   // Add --patience switch to git diff command. See
   // http://bramcohen.livejournal.com/73318.html for
diff --git a/git_gutter_handler.py b/git_gutter_handler.py
index ffc7a7c7..176df41f 100644
--- a/git_gutter_handler.py
+++ b/git_gutter_handler.py
@@ -32,6 +32,7 @@ def __init__(self, view):
         self.git_tree = None
         self.git_dir = None
         self.git_path = None
+        self.git_tracked = False
 
         self._last_refresh_time_git_file = 0
 
@@ -82,6 +83,14 @@ def _get_view_encoding(self):
         origin_encoding = self.view.settings().get('origin_encoding')
         return origin_encoding or encoding
 
+    def in_repo(self):
+        """Return true, if the most recent `git show` returned any content.
+
+        If `git show` returns empty content, any diff will result in
+        all lines added state and the view's file is most commonly untracked.
+        """
+        return self.git_tracked
+
     def on_disk(self):
         """Determine, if the view is saved to disk."""
         file_name = self.view.file_name()
@@ -125,6 +134,7 @@ def update_git_file(self):
         def write_file(contents):
             contents = contents.replace(b'\r\n', b'\n')
             contents = contents.replace(b'\r', b'\n')
+            self.git_tracked = bool(contents)
             with open(self.git_temp_file, 'wb') as f:
                 f.write(contents)
 
diff --git a/git_gutter_popup.py b/git_gutter_popup.py
index e13b6fa0..199be865 100644
--- a/git_gutter_popup.py
+++ b/git_gutter_popup.py
@@ -22,12 +22,10 @@
 
 
 def show_diff_popup(view, point, git_handler, highlight_diff=False, flags=0):
-    if not _MDPOPUPS_INSTALLED:
-        return
-
-    line = view.rowcol(point)[0] + 1
-    git_handler.diff_line_change(line).then(
-        partial(_show_diff_popup_impl, view, point, highlight_diff, flags))
+    if _MDPOPUPS_INSTALLED and git_handler.in_repo():
+        line = view.rowcol(point)[0] + 1
+        git_handler.diff_line_change(line).then(
+            partial(_show_diff_popup_impl, view, point, highlight_diff, flags))
 
 
 def _show_diff_popup_impl(view, point, highlight_diff, flags, diff_info):
diff --git a/git_gutter_show_diff.py b/git_gutter_show_diff.py
index bfa5e458..0b400153 100644
--- a/git_gutter_show_diff.py
+++ b/git_gutter_show_diff.py
@@ -21,45 +21,43 @@ def __init__(self, view, git_handler):
         self.view = view
         self.git_handler = git_handler
         self.diff_results = None
+        self.show_untracked = False
 
     def run(self):
         self.git_handler.diff().then(self._check_ignored_or_untracked)
 
     def _check_ignored_or_untracked(self, contents):
-        show_untracked = settings.get(
-            'show_markers_on_untracked_file', False)
-        if show_untracked and self._are_all_lines_added(contents):
-            def bind_ignored_or_untracked(is_ignored):
-                if is_ignored:
-                    self._bind_files('ignored')
-                else:
-                    def bind_untracked(is_untracked):
-                        if is_untracked:
-                            self._bind_files('untracked')
-                        else:
-                            self._lazy_update_ui(contents)
-                    self.git_handler.untracked().then(bind_untracked)
-
-            self.git_handler.ignored().then(bind_ignored_or_untracked)
-            return
-        self._lazy_update_ui(contents)
-
-    # heuristic to determine if the file is either untracked or ignored: all
-    # lines show up as "inserted" in the diff. Relying on the output of the
-    # normal diff command to trigger the actual untracked / ignored check (which
-    # is expensive because it's two separate git ls-files calls) allows us to
-    # save the extra git calls
-    def _are_all_lines_added(self, contents):
-        inserted, modified, deleted = contents
-        if len(modified) == 0 and len(deleted) == 0:
-            chars = self.view.size()
-            region = sublime.Region(0, chars)
-            return len(self.view.split_by_newlines(region)) == len(inserted)
-        else:
-            return False
-
-    def _lazy_update_ui(self, contents):
-        if self.diff_results is None or self.diff_results != contents:
+        """Check diff result and invoke gutter and status message update.
+
+        Arguments:
+            contentes - a tuble of ([inserted], [modified], [deleted]) lines
+        """
+        if self.git_handler.in_repo() is False:
+            show_untracked = settings.get(
+                'show_markers_on_untracked_file', False)
+            # need to check for ignored or untracked file
+            if show_untracked:
+                def bind_ignored_or_untracked(is_ignored):
+                    if is_ignored:
+                        self._bind_files('ignored')
+                    else:
+                        def bind_untracked(is_untracked):
+                            if is_untracked:
+                                self._bind_files('untracked')
+                            else:
+                                # file was staged but empty
+                                self._bind_files('inserted')
+                        self.git_handler.untracked().then(bind_untracked)
+                self.git_handler.ignored().then(bind_ignored_or_untracked)
+
+            # show_untracked was set to false recently so clear gutter
+            elif self.show_untracked:
+                self._clear_all()
+                self._update_status(0, 0, 0, "", "")
+            self.show_untracked = show_untracked
+
+        # update the if lines changed
+        elif self.diff_results is None or self.diff_results != contents:
             self.diff_results = contents
             self._update_ui(contents)
 
@@ -179,12 +177,7 @@ def _bind_icons(self, event, lines):
             'git_gutter_%s' % event, regions, scope, icon, flags)
 
     def _bind_files(self, event):
-        lines = []
-        line_count = self._total_lines()
-        i = 0
-        while i < line_count:
-            lines += [i + 1]
-            i = i + 1
+        lines = [line + 1 for line in range(self._total_lines())]
         self._bind_icons(event, lines)
 
     def _total_lines(self):