1 # Copyright 2010 -- Robert Toscano
3 import os
.path
, tempfile
9 <popup name="RepositoryManagerPopup">
10 <menuitem action="SvcCommit"/>
11 <menuitem action="SvcPull"/>
12 <menuitem action="SvcFetch"/>
13 <menuitem action="SvcPush"/>
17 def load_emblem(name
):
18 return gtk
.icon_theme_get_default().load_icon(name
, 20, gtk
.ICON_LOOKUP_USE_BUILTIN
)
21 emblems
= { 'synced': load_emblem('emblem-default'),
22 'untracked': load_emblem('emblem-new'),
23 'dirty': load_emblem('emblem-danger'),
24 'staged': load_emblem('emblem-draft') }
27 class RepositoryManager(gtk
.TreeView
):
28 def __init__(self
, repos
, svc_interfaces
, window
, statusbar_id
, commit_msg_header
):
31 self
.svc_interfaces
= svc_interfaces
32 self
.gedit_window
= window
33 self
.statusbar
= window
.get_statusbar()
34 self
.statusbar_id
= statusbar_id
35 self
.commit_msg_header
= commit_msg_header
37 self
.model
= gtk
.ListStore(str, # full path to repo
38 str, # name to be displayed
40 gtk
.gdk
.Pixbuf
) # emblem
42 super(RepositoryManager
, self
).__init
__(self
.model
)
44 self
.set_grid_lines(False)
45 self
.set_headers_clickable(True)
46 self
.append_column(gtk
.TreeViewColumn(None, gtk
.CellRendererPixbuf(), pixbuf
=3))
47 self
.append_column(gtk
.TreeViewColumn('Name', gtk
.CellRendererText(), text
=1))
48 self
.append_column(gtk
.TreeViewColumn('Branch', gtk
.CellRendererText(), text
=2))
49 self
.connect('button-release-event', self
.on_button_released
)
51 # Create the Repository Manager popup
52 self
.uimanager
= gtk
.UIManager()
53 self
.uimanager
.add_ui_from_string(popup_xml
)
55 self
.actiongroup
= gtk
.ActionGroup('SvcBase')
56 self
.actiongroup
.add_actions([ ('SvcCommit', gtk
.STOCK_SAVE_AS
, 'Commit', None,
57 'Commit all staged files', self
.on_svc_commit_all
),
58 ('SvcPush', gtk
.STOCK_GOTO_TOP
, 'Push', None,
59 'Push to origin repository', self
.on_svc_push
),
60 ('SvcPull', gtk
.STOCK_GOTO_BOTTOM
, 'Pull', None,
61 'Pull from remote reposities', self
.on_svc_pull
),
62 ('SvcFetch', gtk
.STOCK_GO_DOWN
, 'Fetch', None,
63 'Fetch from remote repositories', self
.on_svc_fetch
) ])
65 self
.uimanager
.insert_action_group(self
.actiongroup
, 0)
67 self
.commit_tabs
= {} # tab -> repo
68 self
.on_tab_closed_id
= window
.connect('tab-removed', self
.on_tab_closed
)
70 # watch for selection changes and make the actions sensitive as needed
71 self
.get_selection().connect('changed', self
.on_selection_changed
)
74 def update_root(self
, root
):
75 '''Adds/removes repos to/from the RM based on the new root and each repo's path'''
80 for path
in self
.repos
.keys():
81 if path
.startswith(self
.curr_root
): toadd
.append(path
)
85 for row
in self
.model
:
86 if not row
[0].startswith(self
.curr_root
): toremove
.append(row
)
87 else: tokeep
.append(row
[0])
89 # remove paths already in the model from toadd
90 for path
in tokeep
: toadd
.remove(path
)
92 # remove paths from the model
94 self
.model
.remove(row
.iter)
96 # modify existing rows to match new root
97 for row
in self
.model
:
98 if row
[0] == self
.curr_root
: row
[1] = os
.path
.basename(row
[0])
99 elif self
.curr_root
.startswith(row
[0]): row
[1] = os
.path
.basename(row
[0])
100 else: row
[1] = '.'+row
[0][len(self
.curr_root
):]
104 self
.add_repo(self
.repos
[path
])
107 def get_emblem(self
, repo
):
108 if repo
.path
in repo
.state
['untracked']: return emblems
['untracked']
109 elif repo
.path
in repo
.state
['dirty']: return emblems
['dirty']
110 elif repo
.path
in repo
.state
['staged']: return emblems
['staged']
111 else: return emblems
['synced']
114 def add_repo(self
, repo
):
115 if repo
.path
== self
.curr_root
:
116 name
= os
.path
.basename(repo
.path
)
118 name
= '.'+repo
.path
[len(self
.curr_root
):]
120 self
.iters
[repo
.path
] = self
.model
.append( ( repo
.path
,
122 self
.get_branch(repo
),
123 self
.get_emblem(repo
) ) )
126 def update_repo(self
, repo
):
127 # update emblem of row
128 self
.model
.set_value( self
.iters
[repo
.path
], 3, self
.get_emblem(repo
) )
131 def on_button_released(self
, widget
, event
):
132 if event
.button
== 3: # right-click
134 self
.uimanager
.get_widget('/RepositoryManagerPopup').popup(None, None, None, event
.button
, 0)
137 def on_svc_commit_all(self
, action
):
138 model
, rows
= self
.get_selection().get_selected_rows()
141 gtk
.MessageDialog().run()
144 repo_path
= model
[rows
[0]][0]
145 repo
= self
.repos
[repo_path
]
147 f
= tempfile
.NamedTemporaryFile(suffix
='.commit',
148 prefix
='gedit-'+repo
.type+'-commit-message-',
150 f
.write( self
.commit_msg_header
+ self
.svc_interfaces
[repo
.type].status_msg(repo
.path
) )
155 tab
= self
.gedit_window
.create_tab_from_uri('file://'+msg_path
,
156 gedit
.encoding_get_utf8(), 0, False, True)
157 tab
.get_document().goto_line(0)
158 self
.commit_tabs
[tab
] = repo
160 def on_svc_pull(self
, action
):
161 model
, rows
= self
.get_selection().get_selected_rows()
163 for path
in [ row
[0] for row
in rows
]:
166 def on_svc_push(self
, action
):
167 model
, rows
= self
.get_selection().get_selected_rows()
169 for path
in [ row
[0] for row
in rows
]:
172 def on_svc_fetch(self
, action
):
173 model
, rows
= self
.get_selection().get_selected_rows()
175 for repo_path
in [ model
[row
][0] for row
in rows
]:
176 repo
= self
.repos
[repo_path
]
177 self
.statusbar
.flash_message(self
.statusbar_id
, 'Fetching repository: '+repo
.path
)
178 self
.svc_interfaces
[repo
.type].fetch(repo
.path
)
181 def on_tab_closed(self
, window
, tab
):
182 if not tab
in self
.commit_tabs
.keys(): return
184 repo
= self
.commit_tabs
[tab
]
185 commit_msg_path
= tab
.get_document().get_uri()[len('file://'):]
187 # check if commit_msg had any text in it
189 f
= open(commit_msg_path
, 'r')
191 line
= line
.strip(' \n')
192 if line
.startswith('#'):
195 print 'Line has message: \''+line
+'\''
201 self
.svc_interfaces
[repo
.type].commit( repo
.path
, commit_msg_path
)
204 del self
.commit_tabs
[tab
]
205 os
.remove(commit_msg_path
)
208 def on_selection_changed(self
, selection
):
209 model
, rows
= selection
.get_selected_rows()
212 for action
in self
.actiongroup
.list_actions():
213 action
.set_sensitive(False)
216 selected_path
= model
[rows
[0]][0]
218 if len(self
.repos
[selected_path
].state
['staged']) == 0:
219 for action
in self
.actiongroup
.list_actions():
220 action
.set_sensitive(True)
221 self
.actiongroup
.get_action('SvcCommit').set_sensitive(False)
224 for action
in self
.actiongroup
.list_actions():
225 action
.set_sensitive(True)
228 def get_branch(self
, repo
):