[gedit-plugins] Move finding the repository to an AppActivatable
- From: Garrett Regier <gregier src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gedit-plugins] Move finding the repository to an AppActivatable
- Date: Sun, 17 Aug 2014 22:44:47 +0000 (UTC)
commit e878501e149913c9f0b71a69620352a15fb7c4f6
Author: Garrett Regier <garrettregier gmail com>
Date: Sun Jun 29 04:45:36 2014 -0700
Move finding the repository to an AppActivatable
This also fixes various issues when the file browser is showing
multiple repositories or the root itself is not a repository.
plugins/git/Makefile.am | 1 +
plugins/git/git/__init__.py | 1 +
plugins/git/git/appactivatable.py | 96 ++++++++++++++++++++++++++++++++++
plugins/git/git/viewactivatable.py | 23 ++++----
plugins/git/git/windowactivatable.py | 79 ++++++++++++++++------------
5 files changed, 154 insertions(+), 46 deletions(-)
---
diff --git a/plugins/git/Makefile.am b/plugins/git/Makefile.am
index 6ba229e..d66223a 100644
--- a/plugins/git/Makefile.am
+++ b/plugins/git/Makefile.am
@@ -2,6 +2,7 @@ if ENABLE_GIT
plugins_gitdir = $(plugindir)/git
plugins_git_PYTHON = \
plugins/git/git/__init__.py \
+ plugins/git/git/appactivatable.py \
plugins/git/git/debug.py \
plugins/git/git/diffrenderer.py \
plugins/git/git/viewactivatable.py \
diff --git a/plugins/git/git/__init__.py b/plugins/git/git/__init__.py
index bcb2787..d015f98 100644
--- a/plugins/git/git/__init__.py
+++ b/plugins/git/git/__init__.py
@@ -17,6 +17,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330,
# Boston, MA 02111-1307, USA.
+from .appactivatable import GitAppActivatable
from .viewactivatable import GitViewActivatable
from .windowactivatable import GitWindowActivatable
diff --git a/plugins/git/git/appactivatable.py b/plugins/git/git/appactivatable.py
new file mode 100644
index 0000000..2dc6cc3
--- /dev/null
+++ b/plugins/git/git/appactivatable.py
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (C) 2014 - Garrett Regier
+#
+# This program 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.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307, USA.
+
+from gi.repository import GLib, GObject, Gio, Gedit, Ggit
+
+import weakref
+
+
+class GitAppActivatable(GObject.Object, Gedit.AppActivatable):
+ app = GObject.property(type=Gedit.App)
+
+ __instance = None
+
+ def __init__(self):
+ super().__init__()
+
+ Ggit.init()
+
+ GitAppActivatable.__instance = self
+
+ def do_activate(self):
+ self.__repos = weakref.WeakValueDictionary()
+
+ def do_deactivate(self):
+ self.__repos = None
+
+ @classmethod
+ def get_instance(cls):
+ return cls.__instance
+
+ def get_repository(self, location, is_dir):
+ dir_location = location if is_dir else location.get_parent()
+ dir_uri = dir_location.get_uri()
+
+ # Fast Path
+ try:
+ return self.__repos[dir_uri]
+
+ except KeyError:
+ pass
+
+ # Doing remote operations is too slow
+ if not location.has_uri_scheme('file'):
+ return None
+
+ # Must check every dir, otherwise submodules will have issues
+ try:
+ repo_file = Ggit.Repository.discover(location)
+ repo_uri = repo_file.get_parent().get_uri()
+
+ # Reuse the repo if requested multiple times
+ try:
+ repo = self.__repos[repo_uri]
+
+ except KeyError:
+ repo = Ggit.Repository.open(repo_file)
+
+ # 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.get_workdir().get_uri()] = repo
+ #print(repo.get_workdir().get_uri())
+
+ except Exception:
+ return None
+
+ while dir_uri not in self.__repos:
+ #print(dir_uri)
+
+ self.__repos[dir_uri] = repo
+ dir_location = dir_location.get_parent()
+ dir_uri = dir_location.get_uri()
+
+ return repo
+
+# ex:ts=4:et:
diff --git a/plugins/git/git/viewactivatable.py b/plugins/git/git/viewactivatable.py
index 7eff837..f3a4173 100644
--- a/plugins/git/git/viewactivatable.py
+++ b/plugins/git/git/viewactivatable.py
@@ -18,6 +18,8 @@
# Boston, MA 02111-1307, USA.
from gi.repository import GLib, GObject, Gtk, Gedit, Ggit
+
+from .appactivatable import GitAppActivatable
from .diffrenderer import DiffType, DiffRenderer
from .windowactivatable import GitWindowActivatable
@@ -48,6 +50,8 @@ class GitViewActivatable(GObject.Object, Gedit.ViewActivatable):
def do_activate(self):
GitWindowActivatable.register_view_activatable(self)
+ self.app_activatable = GitAppActivatable.get_instance()
+
self.diff_renderer = DiffRenderer()
self.gutter = self.view.get_gutter(Gtk.TextWindowType.LEFT)
@@ -102,19 +106,10 @@ class GitViewActivatable(GObject.Object, Gedit.ViewActivatable):
def update_location(self, *args):
self.location = self.buffer.get_file().get_location()
- repo = None
- if self.location is not None and self.location.has_uri_scheme('file'):
- try:
- repo_file = Ggit.Repository.discover(self.location)
- repo = Ggit.Repository.open(repo_file)
- head = repo.get_head()
- commit = repo.lookup(head.get_target(), Ggit.Commit.__gtype__)
- tree = commit.get_tree()
+ if self.location is not None:
+ repo = self.app_activatable.get_repository(self.location, False)
- except Exception:
- repo = None
-
- if repo is None:
+ if self.location is None or repo is None:
if self.file_contents_list is not None:
self.file_contents_list = None
self.gutter.remove(self.diff_renderer)
@@ -129,6 +124,10 @@ class GitViewActivatable(GObject.Object, Gedit.ViewActivatable):
self.update))
try:
+ head = repo.get_head()
+ commit = repo.lookup(head.get_target(), Ggit.Commit.__gtype__)
+ tree = commit.get_tree()
+
relative_path = repo.get_workdir().get_relative_path(self.location)
entry = tree.get_by_path(relative_path)
diff --git a/plugins/git/git/windowactivatable.py b/plugins/git/git/windowactivatable.py
index 02f4cd1..6248506 100644
--- a/plugins/git/git/windowactivatable.py
+++ b/plugins/git/git/windowactivatable.py
@@ -22,6 +22,7 @@ from gi.repository import GLib, GObject, Gio, Gedit, Ggit
import collections.abc
import weakref
+from .appactivatable import GitAppActivatable
from .debug import debug
from .workerthread import WorkerThread
@@ -104,13 +105,8 @@ class GitWindowActivatable(GObject.Object, Gedit.WindowActivatable):
def __init__(self):
super().__init__()
- Ggit.init()
-
self.view_activatables = weakref.WeakSet()
- self.repo = None
- self.tree = None
-
@classmethod
def register_view_activatable(cls, view_activatable):
window = view_activatable.view.get_toplevel()
@@ -130,6 +126,8 @@ class GitWindowActivatable(GObject.Object, Gedit.WindowActivatable):
# self.window is not set until now
self.windows[self.window] = self
+ self.app_activatable = GitAppActivatable.get_instance()
+
self.bus = self.window.get_message_bus()
self.git_status_thread = GitStatusThread(self.update_location)
@@ -164,8 +162,6 @@ class GitWindowActivatable(GObject.Object, Gedit.WindowActivatable):
for sid in self.bus_signals:
self.bus.disconnect(sid)
- self.repo = None
- self.tree = None
self.file_nodes = FileNodes()
self.window_signals = []
self.bus_signals = []
@@ -178,16 +174,18 @@ class GitWindowActivatable(GObject.Object, Gedit.WindowActivatable):
def notify_status(self, view_activatable, psepc):
location = view_activatable.view.get_buffer().get_file().get_location()
+ if location is None:
+ return
+
+ if location not in self.file_nodes:
+ return
- if location is not None:
- self.git_status_thread.push(self.repo, location)
+ repo = self.get_repository(location)
+ if repo is not None:
+ self.git_status_thread.push(repo, location)
def tab_removed(self, window, tab):
view = tab.get_view()
- location = view.get_buffer().get_file().get_location()
-
- if location is None:
- return
# Need to remove the view activatable otherwise update_location()
# might use the view's status and not the file's actual status
@@ -196,14 +194,25 @@ class GitWindowActivatable(GObject.Object, Gedit.WindowActivatable):
self.view_activatables.remove(view_activatable)
break
- self.git_status_thread.push(self.repo, location)
+ location = view.get_buffer().get_file().get_location()
+ if location is None:
+ return
+
+ repo = self.get_repository(location)
+ if repo is not None:
+ self.git_status_thread.push(repo, location)
def focus_in_event(self, window, event):
for view_activatable in self.view_activatables:
view_activatable.update()
for location in self.file_nodes:
- self.git_status_thread.push(self.repo, location)
+ repo = self.get_repository(location)
+ if repo is not None:
+ self.git_status_thread.push(repo, location)
+
+ def get_repository(self, location, is_dir=False):
+ return self.app_activatable.get_repository(location, is_dir)
def root_changed(self, bus, msg, data=None):
self.clear_monitors()
@@ -211,29 +220,28 @@ class GitWindowActivatable(GObject.Object, Gedit.WindowActivatable):
self.file_nodes = FileNodes()
location = msg.location
- if not location.has_uri_scheme('file'):
- return
- try:
- repo_file = Ggit.Repository.discover(location)
- self.repo = Ggit.Repository.open(repo_file)
- head = self.repo.get_head()
- commit = self.repo.lookup(head.get_target(), Ggit.Commit.__gtype__)
- self.tree = commit.get_tree()
+ repo = self.get_repository(location, True)
+ if repo is None:
+ return
- except Exception:
- self.repo = None
- self.tree = None
+ # Avoid the .git dir
+ repo_location = repo.get_location()
+ if location.get_uri().startswith(repo_location.get_uri()):
+ return
- else:
- self.monitor_directory(location)
+ self.monitor_directory(location)
def inserted(self, bus, msg, data=None):
- if self.repo is None:
+ location = msg.location
+
+ repo = self.get_repository(location, msg.is_directory)
+ if repo is None:
return
- location = msg.location
- if not location.has_uri_scheme('file'):
+ # Avoid the .git dir
+ repo_location = repo.get_location()
+ if location.get_uri().startswith(repo_location.get_uri()):
return
if msg.is_directory:
@@ -241,13 +249,14 @@ class GitWindowActivatable(GObject.Object, Gedit.WindowActivatable):
else:
self.file_nodes[location] = FileNode(msg)
- self.git_status_thread.push(self.repo, location)
+ self.git_status_thread.push(repo, location)
def deleted(self, bus, msg, data=None):
# File browser's deleted signal is broken
return
- uri = msg.location.get_uri()
+ location = msg.location
+ uri = location.get_uri()
if uri in self.monitors:
self.monitors[uri].cancel()
@@ -313,6 +322,8 @@ class GitWindowActivatable(GObject.Object, Gedit.WindowActivatable):
if event_type == Gio.FileMonitorEvent.CHANGED:
for f in (file, other_file):
if f is not None and f in self.file_nodes:
- self.git_status_thread.push(self.repo, f)
+ repo = self.get_repository(f)
+ if repo is not None:
+ self.git_status_thread.push(repo, f)
# ex:ts=4:et:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]