From c0182c501d9dba75ac958c57e9e5d8a3391d5ce2 Mon Sep 17 00:00:00 2001 From: Robert L Toscano Date: Tue, 11 Aug 2009 02:23:35 +0200 Subject: [PATCH] Now implemented git diff and other fixes # To cancel this commit close this file without making a change. To commit, # write your message, then save and close the file. # # On branch master # Your branch is ahead of 'origin/master' by 1 commit. # # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # modified: git.py # modified: giterdone.gedit-plugin # modified: giterdone.py # --- git.py | 9 +++ giterdone.gedit-plugin | 2 +- giterdone.py | 180 +++++++++++++++++++++++++++++++------------------ 3 files changed, 126 insertions(+), 65 deletions(-) diff --git a/git.py b/git.py index df9efeb..97d2c16 100644 --- a/git.py +++ b/git.py @@ -226,3 +226,12 @@ def find_repo(path): cur_dir = os.path.sep.join(os.path.split(cur_dir)[:-1]) return None + +def diff(path): + git_dir = find_repo(path) + if not git_dir: return 'File not in a git repository' + + p = subprocess.Popen(['git', 'diff', path], cwd=git_dir, stdout=subprocess.PIPE) + stdout, stderr = p.communicate() + + return stdout diff --git a/giterdone.gedit-plugin b/giterdone.gedit-plugin index cc0601e..0bf8955 100644 --- a/giterdone.gedit-plugin +++ b/giterdone.gedit-plugin @@ -6,4 +6,4 @@ Name=Git & File-Browser integration Description=A Git overlay on the File Browser Plugin Authors=Robert Lopez Toscano Copyright=Copyright © 2009 Robert Lopez Toscano -#Website=http://www.gedit.org +Website=http://rltoscano.dnsalias.com/giterdone diff --git a/giterdone.py b/giterdone.py index efe2977..9c6e0b1 100644 --- a/giterdone.py +++ b/giterdone.py @@ -1,10 +1,19 @@ # Copyright 2009 -- Robert Toscano -import os, glib -import gtk, gedit +import os +import glib, gtk, gedit import git +def unique_path(prefix): + suffix = 0 + path = prefix+str(suffix) + while os.path.exists(path): + suffix += 1 + path = prefix+str(suffix) + return path + + class Giterdone(gedit.Plugin): commit_msg_header = ''' @@ -26,50 +35,72 @@ class Giterdone(gedit.Plugin): self.bus_ids.append( mb.connect('/plugins/filebrowser', 'begin_loading', self.fb_begin_loading) ) self.bus_ids.append( mb.connect('/plugins/filebrowser', 'end_loading', self.fb_end_loading) ) - # get the filebrowser view - fb_widget = None - sp = self.window.get_side_panel() - for child in sp.get_children(): - if isinstance(child, gtk.Notebook): - for page in child.get_children(): - if page.get_name() == 'GeditFileBrowserWidget': - fb_widget = page - break - break - fb_view = fb_widget.get_children()[2].get_children()[0] - - # add git-add context menu-item - self.git_add_action = gtk.Action('git-add', 'git add', - 'Add file to staging area', gtk.STOCK_ADD) - self.on_git_add_id = self.git_add_action.connect('activate', self.on_git_add, fb_view) - msg = mb.send_sync('/plugins/filebrowser', 'add_context_item', - action=self.git_add_action, path='ui/Popup/Popup_Opt3') - - # add git-commit context menu-item - self.git_commit_action = gtk.Action('git-commit','git commit', - 'Commit staged files', gtk.STOCK_SAVE_AS) - self.on_git_commit_id = self.git_commit_action.connect('activate', self.on_git_commit, - fb_view) - msg = mb.send_sync('/plugins/filebrowser', 'add_context_item', - action=self.git_commit_action, path='ui/Popup/Popup_Opt3') - - # listen for tab closes (these might be gedit commit messages + self.fb_action_ids = {} + + major, minor, rev = gedit.version + if major >= 2 and minor >= 26 and rev >= 3: + # get the filebrowser view + fb_widget = None + sp = self.window.get_side_panel() + for child in sp.get_children(): + if isinstance(child, gtk.Notebook): + for page in child.get_children(): + if page.get_name() == 'GeditFileBrowserWidget': + fb_widget = page + break + break + fb_view = fb_widget.get_children()[2].get_children()[0] + + # git-add context-menu item + add_action = gtk.Action('git-add', 'git add', + 'Add file to staging area', gtk.STOCK_ADD) + self.fb_action_ids[add_action] = add_action.connect('activate', + self.on_git_add, + fb_view) + mb.send_sync('/plugins/filebrowser', 'add_context_item', + action=add_action, path='ui/Popup/Popup_Opt3') + + # git-commit context-menu item + commit_action = gtk.Action('git-commit','git commit', + 'Commit staged files', gtk.STOCK_SAVE_AS) + self.fb_action_ids[commit_action] = commit_action.connect('activate', + self.on_git_commit, + fb_view) + mb.send_sync('/plugins/filebrowser', 'add_context_item', + action=commit_action, path='ui/Popup/Popup_Opt3') + + # git-diff context-menu item + diff_action = gtk.Action('git-diff','git diff', + 'Diff file', gtk.STOCK_COPY) + self.fb_action_ids[diff_action] = diff_action.connect('activate', + self.on_git_diff, + fb_view) + mb.send_sync('/plugins/filebrowser', 'add_context_item', + action=diff_action, path='ui/Popup/Popup_Opt3') + self.commit_tabs = {} - self.window.connect('tab-removed', self.on_tab_closed) + self.diff_tabs = [] + + # listen for tab closes (these might be git commit messages or git diffs) + self.on_tab_closed_id = self.window.connect('tab-removed', self.on_tab_closed) + + # generate a status-bar context id + self.status_id = self.window.get_statusbar().get_context_id('giterdone') self.repos = {} self.ids = {} self.repo_hashes = {} self.deactivating = False + # check repos for changes every second, but only do it when idle glib.timeout_add(1000, self.check_repos, priority=glib.PRIORITY_DEFAULT_IDLE) def deactivate(self, window): print 'deactivated' self.deactivating = True - self.git_add_action.disconnect(self.on_git_add_id) - self.git_commit_action.disconnect(self.on_git_commit_id) + for action, id in self.fb_action_ids.iteritems(): action.disconnect(id) + self.window.disconnect(self.on_tab_closed_id) bus = self.window.get_message_bus() for bus_id in self.bus_ids: bus.disconnect(bus_id) @@ -138,19 +169,13 @@ class Giterdone(gedit.Plugin): print 'on git add' model, rows = view.get_selection().get_selected_rows() - uris = [ model[row][2][7:] for row in rows ] + paths = [ model[row][2][len('file://'):] for row in rows ] - successful = git.add(uris) + git.add(paths) - if successful: - for uri in uris: - # update repos - git_dir = git.find_repo(uri) - repo = self.repos[git_dir] - if uri in repo['untracked']: repo['untracked'].remove(uri) - if uri in repo['dirty']: repo['dirty'].remove(uri) - self.window.get_message_bus().send('/plugins/filebrowser', 'set_emblem', - id=self.ids[uri], emblem='emblem-cvs-added') + # flash statusbar message + msg = 'Added '+str( len(paths) )+' files to their respective repositories' + self.window.get_statusbar().flash_message(self.status_id, msg) def on_git_commit(self, action, view): @@ -160,41 +185,49 @@ class Giterdone(gedit.Plugin): uris = [ model[row][2][7:] for row in rows ] git_dir = git.find_repo(uris[0]) - commit_msg_path = '/tmp/gedit-git-commit-message' + + commit_msg_path = unique_path('/tmp/gedit-git-commit-message-') + f = open(commit_msg_path, 'w') f.write( self.commit_msg_header + git.status_msg(git_dir) ) + f.close() # open file in gedit tab = self.window.create_tab_from_uri('file://'+commit_msg_path, gedit.encoding_get_utf8(), 0, False, True) + tab.get_document().goto_line(0) self.commit_tabs[tab] = git_dir def on_tab_closed(self, window, tab): - if not tab in self.commit_tabs.keys(): return - git_dir = self.commit_tabs[tab] - commit_msg_path = tab.get_document().get_uri()[len('file://'):] + if tab in self.commit_tabs.keys(): + git_dir = self.commit_tabs[tab] + commit_msg_path = tab.get_document().get_uri()[len('file://'):] - git.commit(git_dir, commit_msg_path) + # check if commit_msg had any text in it + has_msg = False + f = open(commit_msg_path, 'r') + for line in f: + line = line.strip(' \n') + if line.startswith('#'): + continue + elif line != '': + print 'Line has message: \''+line+'\'' + has_msg = True + break + f.close() - # change added emblems to defaults - bus = self.window.get_message_bus() - repo = self.repos[git_dir] - for path in repo['staged']: - id = self.ids[path] + if has_msg: + git.commit(git_dir, commit_msg_path) - if path in repo['ignored']: - continue - elif path in repo['dirty']: - bus.send('/plugins/filebrowser', 'set_emblem', id=id, emblem='emblem-cvs-modified') - else: - bus.send('/plugins/filebrowser', 'set_emblem', id=id, emblem='emblem-default') + # clean up + del self.commit_tabs[tab] + os.remove(commit_msg_path) - # clean up - del self.commit_tabs[tab] - os.remove(commit_msg_path) - self.repos[git_dir]['staged'] = [] + elif tab in self.diff_tabs: + self.diff_tabs.remove(tab) + os.remove( tab.get_document().get_uri()[len('file://'):] ) def on_repo_changed(self, git_dir): @@ -218,3 +251,22 @@ class Giterdone(gedit.Plugin): self.on_repo_changed(git_dir) return not self.deactivating + + + def on_git_diff(self, action, view): + model, rows = view.get_selection().get_selected_rows() + + paths = [ model[row][2][len('file://'):] for row in rows ] + + diff = git.diff(paths[0]) + + diff_path = unique_path('/tmp/gedit-git-diff-') + f = open(diff_path, 'w') + f.write(diff) + f.close() + + # open file in gedit + tab = self.window.create_tab_from_uri('file://'+diff_path, + gedit.encoding_get_utf8(), 0, False, True) + tab.get_document().goto_line(0) + self.diff_tabs.append(tab) -- 2.11.4.GIT