[gedit-plugins] git: Only return a repo for a location in the .git dir when explicitly allowed



commit 2e81a575aaacca0278e8829d78b57807ca469cb5
Author: Garrett Regier <garrettregier gmail com>
Date:   Sun Aug 17 18:39:19 2014 -0700

    git: Only return a repo for a location in the .git dir when explicitly allowed
    
    This prevents every caller from needing to check if the location is
    in the repo's .git directory. This also fixes a few places that we were
    not doing this check before which caused various odd behaviors.
    Also, add a debug message if we try to determine the status of a
    location in the .git directory, before this patch it was possible
    and would cause a warning.

 plugins/git/git/appactivatable.py    |   52 +++++++++++++++++++++++----------
 plugins/git/git/windowactivatable.py |   22 +++++---------
 2 files changed, 44 insertions(+), 30 deletions(-)
---
diff --git a/plugins/git/git/appactivatable.py b/plugins/git/git/appactivatable.py
index 3e76aca..2c55175 100644
--- a/plugins/git/git/appactivatable.py
+++ b/plugins/git/git/appactivatable.py
@@ -33,29 +33,41 @@ class GitAppActivatable(GObject.Object, Gedit.AppActivatable):
         GitAppActivatable.__instance = self
 
     def do_activate(self):
-        self.__repos = {}
+        self.clear_repositories()
 
     def do_deactivate(self):
-        self.__repos = None
+        self.__git_repos = None
+        self.__workdir_repos = None
 
     @classmethod
     def get_instance(cls):
         return cls.__instance
 
     def clear_repositories(self):
-        self.__repos = {}
+        self.__git_repos = {}
+        self.__workdir_repos = {}
 
-    def get_repository(self, location, is_dir):
+    def get_repository(self, location, is_dir, *, allow_git_dir=False):
+        # The repos are cached by the directory
         dir_location = location if is_dir else location.get_parent()
         dir_uri = dir_location.get_uri()
 
         # Fast Path
         try:
-            return self.__repos[dir_uri]
+            return self.__workdir_repos[dir_uri]
 
         except KeyError:
             pass
 
+        try:
+            repo = self.__git_repos[dir_uri]
+
+        except KeyError:
+            pass
+
+        else:
+            return repo if allow_git_dir else None
+
         # Doing remote operations is too slow
         if not location.has_uri_scheme('file'):
             return None
@@ -67,42 +79,50 @@ class GitAppActivatable(GObject.Object, Gedit.AppActivatable):
         except GLib.Error:
             # Prevent trying to find a git repository
             # for every file in this directory
-            self.__repos[dir_uri] = None
+            self.__workdir_repos[dir_uri] = None
             return None
 
-        repo_uri = repo_file.get_parent().get_uri()
+        repo_uri = repo_file.get_uri()
 
         # Reuse the repo if requested multiple times
         try:
-            repo = self.__repos[repo_uri]
+            repo = self.__git_repos[repo_uri]
 
         except KeyError:
             repo = Ggit.Repository.open(repo_file)
-            repo_workdir_uri = repo.get_workdir().get_uri()
 
             # TODO: this was around even when not used, on purpose?
             head = repo.get_head()
             commit = repo.lookup(head.get_target(), Ggit.Commit.__gtype__)
             tree = commit.get_tree()
 
-            self.__repos[repo_uri] = repo
-            self.__repos[repo_workdir_uri] = repo
+            self.__git_repos[repo_uri] = repo
+
+        # Need to keep the caches for workdir and
+        # the .git dir separate to support allow_git_dir
+        if dir_uri.startswith(repo_uri):
+            top_uri = repo_uri
+            repos = self.__git_repos
 
         else:
-            repo_workdir_uri = repo.get_workdir().get_uri()
+            top_uri = repo.get_workdir().get_uri()
+            repos = self.__workdir_repos
 
         # Avoid trouble with symbolic links
-        while dir_uri.startswith(repo_workdir_uri):
-            self.__repos[dir_uri] = repo
+        while dir_uri.startswith(top_uri):
+            repos[dir_uri] = repo
 
             dir_location = dir_location.get_parent()
             dir_uri = dir_location.get_uri()
 
             # Avoid caching the repo all the
-            # way up to the workdir each time
-            if dir_uri in self.__repos:
+            # way up to the top dir each time
+            if dir_uri in repos:
                 break
 
+        if repos is self.__git_repos:
+            return repo if allow_git_dir else None
+
         return repo
 
 # ex:ts=4:et:
diff --git a/plugins/git/git/windowactivatable.py b/plugins/git/git/windowactivatable.py
index 3bff179..3fa99ca 100644
--- a/plugins/git/git/windowactivatable.py
+++ b/plugins/git/git/windowactivatable.py
@@ -85,6 +85,12 @@ class GitStatusThread(WorkerThread):
             debug('Invalid repository', print_stack=True)
             return
  
+        git_dir = repo.get_location().get_uri()
+        if location.get_uri().startswith(git_dir):
+            debug('Invalid location: "%s" is in git dir "%s"' %
+                  (location.get_uri(), git_dir), print_stack=True)
+            return
+
         workdir = repo.get_workdir()
         if workdir.get_relative_path(location) is None:
             debug('Invalid location "%s" for workdir "%s"' %
@@ -224,15 +230,8 @@ class GitWindowActivatable(GObject.Object, Gedit.WindowActivatable):
         location = msg.location
 
         repo = self.get_repository(location, True)
-        if repo is None:
-            return
-
-        # Avoid the .git dir
-        repo_location = repo.get_location()
-        if location.get_uri().startswith(repo_location.get_uri()):
-            return
-
-        self.monitor_directory(location)
+        if repo is not None:
+            self.monitor_directory(location)
 
     def inserted(self, bus, msg, data=None):
         location = msg.location
@@ -241,11 +240,6 @@ class GitWindowActivatable(GObject.Object, Gedit.WindowActivatable):
         if repo is None:
             return
 
-        # Avoid the .git dir
-        repo_location = repo.get_location()
-        if location.get_uri().startswith(repo_location.get_uri()):
-            return
-
         if msg.is_directory:
             self.monitor_directory(location)
 


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