/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to nautilus-bzr.py

  • Committer: Jelmer Vernooij
  • Date: 2011-11-17 21:27:30 UTC
  • Revision ID: jelmer@samba.org-20111117212730-j5onzc4tsatiyoqc
Initial work on fixing nautilus-bzr.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
# You can also install nautilus-bzr manually by copying it (or linking it from)
26
26
# ~/.local/share/nautilus-python/extensions/nautilus-bzr.py
27
27
 
28
 
from gi.repository import Gtk
29
 
import nautilus
30
 
from bzrlib.branch import Branch
31
 
from bzrlib.bzrdir import BzrDir
 
28
from gi.repository import Gtk, Nautilus, GObject
 
29
from bzrlib.controldir import ControlDir
32
30
from bzrlib.errors import (
33
31
    NotBranchError,
34
32
    NoWorkingTree,
35
 
    UnsupportedProtocol,
36
33
    )
 
34
from bzrlib.tree import InterTree
37
35
from bzrlib.workingtree import WorkingTree
38
 
from bzrlib.config import GlobalConfig
39
36
 
40
37
from bzrlib.plugin import load_plugins
41
38
load_plugins()
42
39
 
43
 
from bzrlib.plugins.gtk.commands import (
44
 
    cmd_gannotate,
45
 
    start_viz_window,
46
 
    )
47
40
 
48
 
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."""
49
44
 
50
45
    def __init__(self):
51
46
        pass
52
47
 
 
48
    @classmethod
 
49
    def _open_bzrdir(cls, vfs_file):
 
50
        uri = vfs_file.get_uri()
 
51
        controldir, path = ControlDir.open_containing(uri)
 
52
        return controldir, path
 
53
 
53
54
    def add_cb(self, menu, vfs_file):
54
 
        # We can only cope with local files
55
 
        if vfs_file.get_uri_scheme() != 'file':
56
 
            return
57
 
 
58
 
        file = vfs_file.get_uri()
59
 
        try:
60
 
            tree, path = WorkingTree.open_containing(file)
61
 
        except NotBranchError:
62
 
            return
63
 
 
 
55
        controldir, path = self._open_bzrdir(vfs_file)
 
56
        tree = controldir.open_workingtree()
64
57
        tree.add(path)
65
58
 
66
 
        return
67
 
 
68
59
    def ignore_cb(self, menu, vfs_file):
69
60
        # We can only cope with local files
70
 
        if vfs_file.get_uri_scheme() != 'file':
71
 
            return
72
 
 
73
 
        file = vfs_file.get_uri()
74
 
        try:
75
 
            tree, path = WorkingTree.open_containing(file)
76
 
        except NotBranchError:
77
 
            return
78
 
 
79
 
        #FIXME
80
 
 
 
61
        controldir, path = self._open_bzrdir(vfs_file)
 
62
        tree = controldir.open_workingtree()
 
63
        #FIXME: Add path to ignore file
81
64
        return
82
65
 
83
66
    def unignore_cb(self, menu, vfs_file):
84
67
        # We can only cope with local files
85
 
        if vfs_file.get_uri_scheme() != 'file':
86
 
            return
87
 
 
88
 
        file = vfs_file.get_uri()
89
 
        try:
90
 
            tree, path = WorkingTree.open_containing(file)
91
 
        except NotBranchError:
92
 
            return
93
 
 
 
68
        controldir, path = self._open_bzrdir(vfs_file)
 
69
        tree = controldir.open_workingtree()
94
70
        #FIXME
95
 
 
96
71
        return
97
72
 
98
73
    def diff_cb(self, menu, vfs_file):
99
 
        # We can only cope with local files
100
 
        if vfs_file.get_uri_scheme() != 'file':
101
 
            return
102
 
 
103
 
        file = vfs_file.get_uri()
104
 
        try:
105
 
            tree, path = WorkingTree.open_containing(file)
106
 
        except NotBranchError:
107
 
            return
108
 
 
 
74
        controldir, path = self._open_bzrdir(vfs_file)
 
75
        tree = controldir.open_workingtree()
109
76
        from bzrlib.plugins.gtk.diff import DiffWindow
110
77
        window = DiffWindow()
111
78
        window.set_diff(tree.branch._get_nick(local=True), tree, 
115
82
        return
116
83
 
117
84
    def newtree_cb(self, menu, vfs_file):
118
 
        # We can only cope with local files
119
 
        if vfs_file.get_uri_scheme() != 'file':
120
 
            return
121
 
 
122
 
        file = vfs_file.get_uri()
123
 
 
124
 
        # We only want to continue here if we get a NotBranchError
125
 
        try:
126
 
            tree, path = WorkingTree.open_containing(file)
127
 
        except NotBranchError:
128
 
            BzrDir.create_standalone_workingtree(file)
 
85
        controldir, path = self._open_bzrdir(vfs_file)
 
86
        controldir.create_workingtree()
129
87
 
130
88
    def remove_cb(self, menu, vfs_file):
131
 
        # We can only cope with local files
132
 
        if vfs_file.get_uri_scheme() != 'file':
133
 
            return
134
 
 
135
 
        file = vfs_file.get_uri()
136
 
        try:
137
 
            tree, path = WorkingTree.open_containing(file)
138
 
        except NotBranchError:
139
 
            return
140
 
 
 
89
        controldir, path = self._open_bzrdir(vfs_file)
 
90
        tree = controldir.open_workingtree()
141
91
        tree.remove(path)
142
92
 
143
93
    def annotate_cb(self, menu, vfs_file):
144
 
        # We can only cope with local files
145
 
        if vfs_file.get_uri_scheme() != 'file':
146
 
            return
147
 
 
148
 
        file = vfs_file.get_uri()
149
 
 
150
 
        vis = cmd_gannotate()
151
 
        vis.run(file)
 
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)
 
98
        Gtk.main()
152
99
 
153
100
    def clone_cb(self, menu, vfs_file=None):
154
 
        # We can only cope with local files
155
 
        if vfs_file.get_uri_scheme() != 'file':
156
 
            return
157
 
 
158
101
        from bzrlib.plugins.gtk.branch import BranchDialog
159
 
        
 
102
        controldir, path = self._open_bzrdir(vfs_file)
 
103
 
160
104
        dialog = BranchDialog(vfs_file.get_name())
161
105
        response = dialog.run()
162
106
        if response != Gtk.ResponseType.NONE:
163
107
            dialog.hide()
164
108
            dialog.destroy()
165
 
 
 
109
 
166
110
    def commit_cb(self, menu, vfs_file=None):
167
 
        # We can only cope with local files
168
 
        if vfs_file.get_uri_scheme() != 'file':
169
 
            return
170
 
 
171
 
        file = vfs_file.get_uri()
172
 
        tree = None
173
 
        branch = None
174
 
        try:
175
 
            tree, path = WorkingTree.open_containing(file)
176
 
            branch = tree.branch
177
 
        except NotBranchError, e:
178
 
            path = e.path
179
 
            #return
180
 
        except NoWorkingTree, e:
181
 
            path = e.base
182
 
            try:
183
 
                (branch, path) = Branch.open_containing(path)
184
 
            except NotBranchError, e:
185
 
                path = e.path
 
111
        controldir, path = self._open_bzrdir(vfs_file)
 
112
        tree = controldir.open_workingtree()
186
113
 
187
114
        from bzrlib.plugins.gtk.commit import CommitDialog
188
115
        dialog = CommitDialog(tree, path)
192
119
            dialog.destroy()
193
120
 
194
121
    def log_cb(self, menu, vfs_file):
195
 
        # We can only cope with local files
196
 
        if vfs_file.get_uri_scheme() != 'file':
197
 
            return
198
 
 
199
 
        file = vfs_file.get_uri()
200
 
 
201
 
        # We only want to continue here if we get a NotBranchError
202
 
        try:
203
 
            branch, path = Branch.open_containing(file)
204
 
        except NotBranchError:
205
 
            return
206
 
 
 
122
        controldir, path = self._open_bzrdir(vfs_file)
 
123
        branch = controldir.open_branch()
207
124
        pp = start_viz_window(branch, [branch.last_revision()])
208
125
        pp.show()
209
126
        Gtk.main()
210
127
 
211
128
    def pull_cb(self, menu, vfs_file):
212
 
        # We can only cope with local files
213
 
        if vfs_file.get_uri_scheme() != 'file':
214
 
            return
215
 
 
216
 
        file = vfs_file.get_uri()
217
 
 
218
 
        # We only want to continue here if we get a NotBranchError
219
 
        try:
220
 
            tree, path = WorkingTree.open_containing(file)
221
 
        except NotBranchError:
222
 
            return
223
 
 
 
129
        controldir, path = self._open_bzrdir(vfs_file)
 
130
        tree = controldir.open_workingtree()
224
131
        from bzrlib.plugins.gtk.pull import PullDialog
225
132
        dialog = PullDialog(tree, path)
226
133
        dialog.display()
227
134
        Gtk.main()
228
135
 
229
136
    def merge_cb(self, menu, vfs_file):
230
 
        # We can only cope with local files
231
 
        if vfs_file.get_uri_scheme() != 'file':
232
 
            return
233
 
 
234
 
        file = vfs_file.get_uri()
235
 
 
236
 
        # We only want to continue here if we get a NotBranchError
237
 
        try:
238
 
            tree, path = WorkingTree.open_containing(file)
239
 
        except NotBranchError:
240
 
            return
241
 
 
 
137
        controldir, path = self._open_bzrdir(vfs_file)
 
138
        tree = controldir.open_workingtree()
242
139
        from bzrlib.plugins.gtk.merge import MergeDialog
243
140
        dialog = MergeDialog(tree, path)
244
141
        dialog.run()
245
142
        dialog.destroy()
246
143
 
247
144
    def get_background_items(self, window, vfs_file):
248
 
        items = []
249
 
        file = vfs_file.get_uri()
250
 
 
251
145
        try:
252
 
            tree, path = WorkingTree.open_containing(file)
253
 
            disabled_flag = self.check_branch_enabled(tree.branch)
254
 
        except UnsupportedProtocol:
 
146
            controldir, path = self._open_bzrdir(vfs_file)
 
147
        except NotBranchError:
255
148
            return
 
149
        try:
 
150
            branch = controldir.open_branch()
256
151
        except NotBranchError:
257
 
            disabled_flag = self.check_branch_enabled()
258
 
            item = nautilus.MenuItem('BzrNautilus::newtree',
 
152
            items = []
 
153
            item = Nautilus.MenuItem('BzrNautilus::newtree',
259
154
                                 'Make directory versioned',
260
155
                                 'Create new Bazaar tree in this folder')
261
156
            item.connect('activate', self.newtree_cb, vfs_file)
262
157
            items.append(item)
263
158
 
264
 
            item = nautilus.MenuItem('BzrNautilus::clone',
 
159
            item = Nautilus.MenuItem('BzrNautilus::clone',
265
160
                                 'Checkout Bazaar branch ...',
266
161
                                 'Checkout Existing Bazaar Branch')
267
162
            item.connect('activate', self.clone_cb, vfs_file)
268
163
            items.append(item)
269
 
 
270
164
            return items
271
 
        except NoWorkingTree:
272
 
            return
273
 
        
274
 
        if disabled_flag == 'False':
275
 
            item = nautilus.MenuItem('BzrNautilus::enable',
 
165
 
 
166
        items = []
 
167
 
 
168
        nautilus_integration = self.check_branch_enabled(branch)
 
169
        if not nautilus_integration:
 
170
            item = Nautilus.MenuItem('BzrNautilus::enable',
276
171
                                     'Enable Bazaar Plugin for this Branch',
277
172
                                     'Enable Bazaar plugin for nautilus')
278
 
            item.connect('activate', self.toggle_integration, 'True', vfs_file)
279
 
            return item,
 
173
            item.connect('activate', self.toggle_integration, True, vfs_file)
 
174
            return [item]
280
175
        else:
281
 
            item = nautilus.MenuItem('BzrNautilus::disable',
282
 
                                      'Disable Bazaar Plugin this Branch',
283
 
                                      'Disable Bazaar plugin for nautilus')
284
 
            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)
285
180
            items.append(item)
286
181
 
287
 
        item = nautilus.MenuItem('BzrNautilus::log',
 
182
        item = Nautilus.MenuItem('BzrNautilus::log',
288
183
                             'History ...',
289
184
                             'Show Bazaar history')
290
185
        item.connect('activate', self.log_cb, vfs_file)
291
186
        items.append(item)
292
187
 
293
 
        item = nautilus.MenuItem('BzrNautilus::pull',
 
188
        item = Nautilus.MenuItem('BzrNautilus::pull',
294
189
                             'Pull ...',
295
190
                             'Pull from another branch')
296
191
        item.connect('activate', self.pull_cb, vfs_file)
297
192
        items.append(item)
298
193
 
299
 
        item = nautilus.MenuItem('BzrNautilus::merge',
300
 
                             'Merge ...',
301
 
                             'Merge from another branch')
302
 
        item.connect('activate', self.merge_cb, vfs_file)
303
 
        items.append(item)
 
194
        try:
 
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)
 
201
            items.append(item)
 
202
        else:
 
203
            item = Nautilus.MenuItem('BzrNautilus::merge',
 
204
                                 'Merge ...',
 
205
                                 'Merge from another branch')
 
206
            item.connect('activate', self.merge_cb, vfs_file)
 
207
            items.append(item)
304
208
 
305
 
        item = nautilus.MenuItem('BzrNautilus::commit',
306
 
                             'Commit ...',
307
 
                             'Commit Changes')
308
 
        item.connect('activate', self.commit_cb, vfs_file)
309
 
        items.append(item)
 
209
            item = Nautilus.MenuItem('BzrNautilus::commit',
 
210
                                 'Commit ...',
 
211
                                 'Commit Changes')
 
212
            item.connect('activate', self.commit_cb, vfs_file)
 
213
            items.append(item)
310
214
 
311
215
        return items
312
216
 
313
217
    def get_file_items(self, window, files):
314
218
        items = []
315
 
        
316
 
        wtfiles = {}
 
219
 
317
220
        for vfs_file in files:
318
 
            # We can only cope with local files
319
 
            if vfs_file.get_uri_scheme() != 'file':
320
 
                continue
 
221
            controldir, path = self._open_bzrdir(vfs_file)
321
222
 
322
 
            file = vfs_file.get_uri()
323
223
            try:
324
 
                tree, path = WorkingTree.open_containing(file)
325
 
                disabled_flag = self.check_branch_enabled(tree.branch)
326
 
            except NotBranchError:
327
 
                disabled_flag = self.check_branch_enabled()
328
 
                if not vfs_file.is_directory():
329
 
                    continue
330
 
 
331
 
                if disabled_flag == 'False':
332
 
                    return
333
 
 
334
 
                item = nautilus.MenuItem('BzrNautilus::newtree',
335
 
                                     'Make directory versioned',
336
 
                                     'Create new Bazaar tree in %s' % vfs_file.get_name())
337
 
                item.connect('activate', self.newtree_cb, vfs_file)
338
 
                return item,
 
224
                tree = controldir.open_workingtree()
339
225
            except NoWorkingTree:
340
226
                continue
341
 
            # Refresh the list of filestatuses in the working tree
342
 
            if path not in wtfiles.keys():
343
 
                tree.lock_read()
344
 
                for rpath, file_class, kind, id, entry in tree.list_files():
345
 
                    wtfiles[rpath] = file_class
346
 
                tree.unlock()
347
 
                wtfiles[u''] = 'V'
348
 
 
349
 
            if wtfiles[path] == '?':
350
 
                item = nautilus.MenuItem('BzrNautilus::add',
 
227
 
 
228
            nautilus_integration = self.check_branch_enabled(tree.branch)
 
229
            if not nautilus_integration:
 
230
                continue
 
231
 
 
232
            file_id = tree.path2id(path)
 
233
            if file_id is None:
 
234
                item = Nautilus.MenuItem('BzrNautilus::add',
351
235
                                     'Add',
352
236
                                     'Add as versioned file')
353
237
                item.connect('activate', self.add_cb, vfs_file)
354
238
                items.append(item)
355
239
 
356
 
                item = nautilus.MenuItem('BzrNautilus::ignore',
 
240
                item = Nautilus.MenuItem('BzrNautilus::ignore',
357
241
                                     'Ignore',
358
242
                                     'Ignore file for versioning')
359
243
                item.connect('activate', self.ignore_cb, vfs_file)
360
244
                items.append(item)
361
 
            elif wtfiles[path] == 'I':
362
 
                item = nautilus.MenuItem('BzrNautilus::unignore',
 
245
            elif tree.is_ignored(path):
 
246
                item = Nautilus.MenuItem('BzrNautilus::unignore',
363
247
                                     'Unignore',
364
248
                                     'Unignore file for versioning')
365
249
                item.connect('activate', self.unignore_cb, vfs_file)
366
250
                items.append(item)
367
 
            elif wtfiles[path] == 'V':
368
 
                item = nautilus.MenuItem('BzrNautilus::log',
 
251
            else:
 
252
                item = Nautilus.MenuItem('BzrNautilus::log',
369
253
                                 'History ...',
370
254
                                 'List changes')
371
255
                item.connect('activate', self.log_cb, vfs_file)
372
256
                items.append(item)
373
257
 
374
 
                item = nautilus.MenuItem('BzrNautilus::diff',
375
 
                                 'View Changes ...',
376
 
                                 'Show differences')
377
 
                item.connect('activate', self.diff_cb, vfs_file)
378
 
                items.append(item)
379
 
 
380
 
                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',
 
261
                                     'View Changes ...',
 
262
                                     'Show differences')
 
263
                    item.connect('activate', self.diff_cb, vfs_file)
 
264
                    items.append(item)
 
265
 
 
266
                    item = Nautilus.MenuItem('BzrNautilus::commit',
 
267
                                 'Commit ...',
 
268
                                 'Commit Changes')
 
269
                    item.connect('activate', self.commit_cb, vfs_file)
 
270
                    items.append(item)
 
271
 
 
272
                item = Nautilus.MenuItem('BzrNautilus::remove',
381
273
                                     'Remove',
382
274
                                     'Remove this file from versioning')
383
275
                item.connect('activate', self.remove_cb, vfs_file)
384
276
                items.append(item)
385
277
 
386
 
                item = nautilus.MenuItem('BzrNautilus::annotate',
 
278
                item = Nautilus.MenuItem('BzrNautilus::annotate',
387
279
                             'Annotate ...',
388
280
                             'Annotate File Data')
389
281
                item.connect('activate', self.annotate_cb, vfs_file)
390
282
                items.append(item)
391
 
 
392
 
                item = nautilus.MenuItem('BzrNautilus::commit',
393
 
                             'Commit ...',
394
 
                             'Commit Changes')
395
 
                item.connect('activate', self.commit_cb, vfs_file)
396
 
                items.append(item)
397
 
 
398
283
        return items
399
284
 
400
285
    def get_columns(self):
401
 
        return nautilus.Column("BzrNautilus::bzr_status",
402
 
                               "bzr_status",
403
 
                               "Bzr Status",
404
 
                               "Version control status"),
 
286
        return [
 
287
            Nautilus.Column(name="BzrNautilus::bzr_status",
 
288
                            attribute="bzr_status",
 
289
                            label="Status",
 
290
                            description="Version control status"),
 
291
            Nautilus.Column(name="BzrNautilus::bzr_revision",
 
292
                            attribute="bzr_revision",
 
293
                            label="Revision",
 
294
                            description="Last change revision"),
 
295
            ]
405
296
 
406
297
    def update_file_info(self, file):
407
298
 
415
306
        except NoWorkingTree:
416
307
            return   
417
308
 
418
 
        disabled_flag = self.check_branch_enabled(tree.branch)
419
 
        if disabled_flag == 'False':
 
309
        nautilus_integration = self.check_branch_enabled(tree.branch)
 
310
        if not nautilus_integration:
420
311
            return
421
312
 
422
313
        emblem = None
453
344
        else:
454
345
            # FIXME: Check for ignored files
455
346
            status = 'unversioned'
456
 
        
 
347
 
457
348
        if emblem is not None:
458
349
            file.add_emblem(emblem)
459
350
        file.add_string_attribute('bzr_status', status)
460
351
 
461
 
    def check_branch_enabled(self, branch=None):
 
352
    def check_branch_enabled(self, branch):
462
353
        # Supports global disable, but there is currently no UI to do this
463
 
        config = GlobalConfig()
464
 
        disabled_flag = config.get_user_option('nautilus_integration')
465
 
        if disabled_flag != 'False':
466
 
            if branch is not None:
467
 
                config = branch.get_config()
468
 
                disabled_flag = config.get_user_option('nautilus_integration')
469
 
        return disabled_flag
470
 
 
471
 
    def toggle_integration(self, menu, action, vfs_file=None):
472
 
        try:
473
 
            tree, path = WorkingTree.open_containing(vfs_file.get_uri())
474
 
        except NotBranchError:
475
 
            return
476
 
        except NoWorkingTree:
477
 
            return
478
 
        branch = tree.branch
479
 
        if branch is None:
480
 
            config = GlobalConfig()
481
 
        else:
482
 
            config = branch.get_config()
483
 
        config.set_user_option('nautilus_integration', action)
484
 
 
 
354
        config = branch.get_config_stack()
 
355
        return config.get("nautilus_integration")
 
356
 
 
357
    def toggle_integration(self, menu, action, vfs_file):
 
358
        controldir = self._open_bzrdir(vfs_file)
 
359
        branch = controldir.open_branch()
 
360
        config = branch.get_config_stack()
 
361
        config.set("nautilus_integration", action)