3
3
# Copyright (C) 2006 Jeff Bailey
4
4
# Copyright (C) 2006 Wouter van Heyst
5
# Copyright (C) 2006-2008 Jelmer Vernooij <jelmer@samba.org>
7
# Published under the GNU GPL
12
from bzrlib.branch import Branch
13
from bzrlib.bzrdir import BzrDir
14
from bzrlib.errors import NotBranchError, NoWorkingTree, UnsupportedProtocol
15
from bzrlib.tree import file_status
5
# Copyright (C) 2006-2011 Jelmer Vernooij <jelmer@samba.org>
7
# This program is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
18
# along with this program; if not, write to the Free Software
19
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
# setup.py can install nautilus-bzr to the right system folder, if pkg-config
25
# You can also install nautilus-bzr manually by copying it (or linking it from)
26
# ~/.local/share/nautilus-python/extensions/nautilus-bzr.py
28
from gi.repository import Gtk, Nautilus, GObject
29
from bzrlib.controldir import ControlDir
30
from bzrlib.errors import (
34
from bzrlib.tree import InterTree
16
35
from bzrlib.workingtree import WorkingTree
17
from bzrlib.config import GlobalConfig
19
37
from bzrlib.plugin import load_plugins
22
from bzrlib.plugins.gtk import _i18n, cmd_visualise, cmd_gannotate
24
class BzrExtension(nautilus.MenuProvider, nautilus.ColumnProvider, nautilus.InfoProvider):
41
class BazaarExtension(Nautilus.MenuProvider, Nautilus.ColumnProvider,
42
Nautilus.InfoProvider, Nautilus.PropertyPageProvider, GObject.GObject):
43
"""Nautilus extension providing Bazaar integration."""
25
45
def __init__(self):
49
def _open_bzrdir(cls, vfs_file):
50
uri = vfs_file.get_uri()
51
controldir, path = ControlDir.open_containing(uri)
52
return controldir, path
28
54
def add_cb(self, menu, vfs_file):
29
# We can only cope with local files
30
if vfs_file.get_uri_scheme() != 'file':
33
file = vfs_file.get_uri()
35
tree, path = WorkingTree.open_containing(file)
36
except NotBranchError:
55
controldir, path = self._open_bzrdir(vfs_file)
56
tree = controldir.open_workingtree()
43
59
def ignore_cb(self, menu, vfs_file):
44
60
# We can only cope with local files
45
if vfs_file.get_uri_scheme() != 'file':
48
file = vfs_file.get_uri()
50
tree, path = WorkingTree.open_containing(file)
51
except NotBranchError:
61
controldir, path = self._open_bzrdir(vfs_file)
62
tree = controldir.open_workingtree()
63
#FIXME: Add path to ignore file
58
66
def unignore_cb(self, menu, vfs_file):
59
67
# We can only cope with local files
60
if vfs_file.get_uri_scheme() != 'file':
63
file = vfs_file.get_uri()
65
tree, path = WorkingTree.open_containing(file)
66
except NotBranchError:
68
controldir, path = self._open_bzrdir(vfs_file)
69
tree = controldir.open_workingtree()
73
73
def diff_cb(self, menu, vfs_file):
74
# We can only cope with local files
75
if vfs_file.get_uri_scheme() != 'file':
78
file = vfs_file.get_uri()
80
tree, path = WorkingTree.open_containing(file)
81
except NotBranchError:
74
controldir, path = self._open_bzrdir(vfs_file)
75
tree = controldir.open_workingtree()
84
76
from bzrlib.plugins.gtk.diff import DiffWindow
85
77
window = DiffWindow()
86
window.set_diff(tree.branch.nick, tree, tree.branch.basis_tree())
78
window.set_diff(tree.branch._get_nick(local=True), tree,
79
tree.branch.basis_tree())
91
84
def newtree_cb(self, menu, vfs_file):
92
# We can only cope with local files
93
if vfs_file.get_uri_scheme() != 'file':
96
file = vfs_file.get_uri()
98
# We only want to continue here if we get a NotBranchError
100
tree, path = WorkingTree.open_containing(file)
101
except NotBranchError:
102
BzrDir.create_standalone_workingtree(file)
85
controldir, path = self._open_bzrdir(vfs_file)
86
controldir.create_workingtree()
104
88
def remove_cb(self, menu, vfs_file):
105
# We can only cope with local files
106
if vfs_file.get_uri_scheme() != 'file':
109
file = vfs_file.get_uri()
111
tree, path = WorkingTree.open_containing(file)
112
except NotBranchError:
89
controldir, path = self._open_bzrdir(vfs_file)
90
tree = controldir.open_workingtree()
117
93
def annotate_cb(self, menu, vfs_file):
118
# We can only cope with local files
119
if vfs_file.get_uri_scheme() != 'file':
122
file = vfs_file.get_uri()
124
vis = cmd_gannotate()
94
from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
95
controldir, path = self._open_bzrdir(vfs_file)
96
win = GAnnotateWindow()
97
win.annotate(controldir.open_workingtree(), controldir.open_branch(), path)
127
100
def clone_cb(self, menu, vfs_file=None):
128
# We can only cope with local files
129
if vfs_file.get_uri_scheme() != 'file':
132
101
from bzrlib.plugins.gtk.branch import BranchDialog
102
controldir, path = self._open_bzrdir(vfs_file)
134
104
dialog = BranchDialog(vfs_file.get_name())
135
105
response = dialog.run()
136
if response != gtk.RESPONSE_NONE:
106
if response != Gtk.ResponseType.NONE:
140
110
def commit_cb(self, menu, vfs_file=None):
141
# We can only cope with local files
142
if vfs_file.get_uri_scheme() != 'file':
145
file = vfs_file.get_uri()
149
tree, path = WorkingTree.open_containing(file)
151
except NotBranchError, e:
154
except NoWorkingTree, e:
157
(branch, path) = Branch.open_containing(path)
158
except NotBranchError, e:
111
controldir, path = self._open_bzrdir(vfs_file)
112
tree = controldir.open_workingtree()
161
114
from bzrlib.plugins.gtk.commit import CommitDialog
162
115
dialog = CommitDialog(tree, path)
163
116
response = dialog.run()
164
if response != gtk.RESPONSE_NONE:
117
if response != Gtk.ResponseType.NONE:
168
121
def log_cb(self, menu, vfs_file):
169
# We can only cope with local files
170
if vfs_file.get_uri_scheme() != 'file':
173
file = vfs_file.get_uri()
175
# We only want to continue here if we get a NotBranchError
177
tree, path = WorkingTree.open_containing(file)
178
except NotBranchError:
181
vis = cmd_visualise()
122
controldir, path = self._open_bzrdir(vfs_file)
123
branch = controldir.open_branch()
124
pp = start_viz_window(branch, [branch.last_revision()])
186
128
def pull_cb(self, menu, vfs_file):
187
# We can only cope with local files
188
if vfs_file.get_uri_scheme() != 'file':
191
file = vfs_file.get_uri()
193
# We only want to continue here if we get a NotBranchError
195
tree, path = WorkingTree.open_containing(file)
196
except NotBranchError:
129
controldir, path = self._open_bzrdir(vfs_file)
130
tree = controldir.open_workingtree()
199
131
from bzrlib.plugins.gtk.pull import PullDialog
200
132
dialog = PullDialog(tree, path)
204
136
def merge_cb(self, menu, vfs_file):
205
# We can only cope with local files
206
if vfs_file.get_uri_scheme() != 'file':
209
file = vfs_file.get_uri()
211
# We only want to continue here if we get a NotBranchError
213
tree, path = WorkingTree.open_containing(file)
214
except NotBranchError:
137
controldir, path = self._open_bzrdir(vfs_file)
138
tree = controldir.open_workingtree()
217
139
from bzrlib.plugins.gtk.merge import MergeDialog
218
140
dialog = MergeDialog(tree, path)
222
144
def get_background_items(self, window, vfs_file):
224
file = vfs_file.get_uri()
227
tree, path = WorkingTree.open_containing(file)
228
disabled_flag = self.check_branch_enabled(tree.branch)
229
except UnsupportedProtocol:
146
controldir, path = self._open_bzrdir(vfs_file)
147
except NotBranchError:
150
branch = controldir.open_branch()
231
151
except NotBranchError:
232
disabled_flag = self.check_branch_enabled()
233
item = nautilus.MenuItem('BzrNautilus::newtree',
153
item = Nautilus.MenuItem('BzrNautilus::newtree',
234
154
'Make directory versioned',
235
155
'Create new Bazaar tree in this folder')
236
156
item.connect('activate', self.newtree_cb, vfs_file)
237
157
items.append(item)
239
item = nautilus.MenuItem('BzrNautilus::clone',
240
'Checkout Bazaar branch',
159
item = Nautilus.MenuItem('BzrNautilus::clone',
160
'Checkout Bazaar branch ...',
241
161
'Checkout Existing Bazaar Branch')
242
162
item.connect('activate', self.clone_cb, vfs_file)
243
163
items.append(item)
246
except NoWorkingTree:
249
if disabled_flag == 'False':
250
item = nautilus.MenuItem('BzrNautilus::enable',
168
nautilus_integration = self.check_branch_enabled(branch)
169
if not nautilus_integration:
170
item = Nautilus.MenuItem('BzrNautilus::enable',
251
171
'Enable Bazaar Plugin for this Branch',
252
172
'Enable Bazaar plugin for nautilus')
253
item.connect('activate', self.toggle_integration, 'True', vfs_file)
173
item.connect('activate', self.toggle_integration, True, vfs_file)
256
item = nautilus.MenuItem('BzrNautilus::disable',
257
'Disable Bazaar Plugin for the Branch',
258
'Disable Bazaar plugin for nautilus')
259
item.connect('activate', self.toggle_integration, 'False', vfs_file)
176
item = Nautilus.MenuItem('BzrNautilus::disable',
177
'Disable Bazaar Plugin this Branch',
178
'Disable Bazaar plugin for nautilus')
179
item.connect('activate', self.toggle_integration, False, vfs_file)
260
180
items.append(item)
262
item = nautilus.MenuItem('BzrNautilus::log',
182
item = Nautilus.MenuItem('BzrNautilus::log',
264
184
'Show Bazaar history')
265
185
item.connect('activate', self.log_cb, vfs_file)
266
186
items.append(item)
268
item = nautilus.MenuItem('BzrNautilus::pull',
188
item = Nautilus.MenuItem('BzrNautilus::pull',
270
190
'Pull from another branch')
271
191
item.connect('activate', self.pull_cb, vfs_file)
272
192
items.append(item)
274
item = nautilus.MenuItem('BzrNautilus::merge',
276
'Merge from another branch')
277
item.connect('activate', self.merge_cb, vfs_file)
195
tree = controldir.open_workingtree()
196
except NoWorkingTree:
197
item = Nautilus.MenuItem('BzrNautilus::create_tree',
198
'Create working tree...',
199
'Create a working tree for this branch')
200
item.connect('activate', self.create_tree_cb, vfs_file)
203
item = Nautilus.MenuItem('BzrNautilus::merge',
205
'Merge from another branch')
206
item.connect('activate', self.merge_cb, vfs_file)
280
item = nautilus.MenuItem('BzrNautilus::commit',
283
item.connect('activate', self.commit_cb, vfs_file)
209
item = Nautilus.MenuItem('BzrNautilus::commit',
212
item.connect('activate', self.commit_cb, vfs_file)
288
217
def get_file_items(self, window, files):
292
220
for vfs_file in files:
293
# We can only cope with local files
294
if vfs_file.get_uri_scheme() != 'file':
221
controldir, path = self._open_bzrdir(vfs_file)
297
file = vfs_file.get_uri()
299
tree, path = WorkingTree.open_containing(file)
300
disabled_flag = self.check_branch_enabled(tree.branch)
301
except NotBranchError:
302
disabled_flag = self.check_branch_enabled()
303
if not vfs_file.is_directory():
306
if disabled_flag == 'False':
309
item = nautilus.MenuItem('BzrNautilus::newtree',
310
'Make directory versioned',
311
'Create new Bazaar tree in %s' % vfs_file.get_name())
312
item.connect('activate', self.newtree_cb, vfs_file)
224
tree = controldir.open_workingtree()
314
225
except NoWorkingTree:
316
# Refresh the list of filestatuses in the working tree
317
if path not in wtfiles.keys():
319
for rpath, file_class, kind, id, entry in tree.list_files():
320
wtfiles[rpath] = file_class
324
if wtfiles[path] == '?':
325
item = nautilus.MenuItem('BzrNautilus::add',
228
nautilus_integration = self.check_branch_enabled(tree.branch)
229
if not nautilus_integration:
232
file_id = tree.path2id(path)
234
item = Nautilus.MenuItem('BzrNautilus::add',
327
236
'Add as versioned file')
328
237
item.connect('activate', self.add_cb, vfs_file)
329
238
items.append(item)
331
item = nautilus.MenuItem('BzrNautilus::ignore',
240
item = Nautilus.MenuItem('BzrNautilus::ignore',
333
242
'Ignore file for versioning')
334
243
item.connect('activate', self.ignore_cb, vfs_file)
335
244
items.append(item)
336
elif wtfiles[path] == 'I':
337
item = nautilus.MenuItem('BzrNautilus::unignore',
245
elif tree.is_ignored(path):
246
item = Nautilus.MenuItem('BzrNautilus::unignore',
339
248
'Unignore file for versioning')
340
249
item.connect('activate', self.unignore_cb, vfs_file)
341
250
items.append(item)
342
elif wtfiles[path] == 'V':
343
item = nautilus.MenuItem('BzrNautilus::log',
252
item = Nautilus.MenuItem('BzrNautilus::log',
346
255
item.connect('activate', self.log_cb, vfs_file)
347
256
items.append(item)
349
item = nautilus.MenuItem('BzrNautilus::diff',
352
item.connect('activate', self.diff_cb, vfs_file)
355
item = nautilus.MenuItem('BzrNautilus::remove',
258
intertree = InterTree.get(tree.basis_tree(), tree)
259
if not intertree.file_content_matches(file_id, file_id):
260
item = Nautilus.MenuItem('BzrNautilus::diff',
263
item.connect('activate', self.diff_cb, vfs_file)
266
item = Nautilus.MenuItem('BzrNautilus::commit',
269
item.connect('activate', self.commit_cb, vfs_file)
272
item = Nautilus.MenuItem('BzrNautilus::remove',
357
274
'Remove this file from versioning')
358
275
item.connect('activate', self.remove_cb, vfs_file)
359
276
items.append(item)
361
item = nautilus.MenuItem('BzrNautilus::annotate',
278
item = Nautilus.MenuItem('BzrNautilus::annotate',
363
280
'Annotate File Data')
364
281
item.connect('activate', self.annotate_cb, vfs_file)
365
282
items.append(item)
367
item = nautilus.MenuItem('BzrNautilus::commit',
370
item.connect('activate', self.commit_cb, vfs_file)
375
285
def get_columns(self):
376
return nautilus.Column("BzrNautilus::bzr_status",
379
"Version control status"),
287
Nautilus.Column(name="BzrNautilus::bzr_status",
288
attribute="bzr_status",
290
description="Version control status"),
291
Nautilus.Column(name="BzrNautilus::bzr_revision",
292
attribute="bzr_revision",
294
description="Last change revision"),
381
297
def update_file_info(self, file):