/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: Vincent Ladeuil
  • Date: 2008-06-10 15:25:47 UTC
  • mto: This revision was merged to the branch mainline in revision 504.
  • Revision ID: v.ladeuil+lp@free.fr-20080610152547-dwmil1p8pd0mfpnl
Fix third failing test (thanks to jam).

* tests/test_commit.py:
(TestPendingRevisions.test_pending_revisions_multi_merge): Fix
provided by jam: bzr we now filter the pending merges so that only
the 'heads()' are included. We just ensure that the pending merges
contain the unique tips for the ancestries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Trivial Bazaar plugin for Nautilus
 
2
#
 
3
# Copyright (C) 2006 Jeff Bailey
 
4
# Copyright (C) 2006 Wouter van Heyst
 
5
# Copyright (C) 2006-2008 Jelmer Vernooij <jelmer@samba.org>
 
6
#
 
7
# Published under the GNU GPL
 
8
 
 
9
import gtk
 
10
import nautilus
 
11
import bzrlib
 
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
 
16
from bzrlib.workingtree import WorkingTree
 
17
from bzrlib.config import GlobalConfig
 
18
 
 
19
from bzrlib.plugin import load_plugins
 
20
load_plugins()
 
21
 
 
22
from bzrlib.plugins.gtk import _i18n, cmd_visualise, cmd_gannotate
 
23
 
 
24
class BzrExtension(nautilus.MenuProvider, nautilus.ColumnProvider, nautilus.InfoProvider):
 
25
    def __init__(self):
 
26
        pass
 
27
 
 
28
    def add_cb(self, menu, vfs_file):
 
29
        # We can only cope with local files
 
30
        if vfs_file.get_uri_scheme() != 'file':
 
31
            return
 
32
 
 
33
        file = vfs_file.get_uri()
 
34
        try:
 
35
            tree, path = WorkingTree.open_containing(file)
 
36
        except NotBranchError:
 
37
            return
 
38
 
 
39
        tree.add(path)
 
40
 
 
41
        return
 
42
 
 
43
    def ignore_cb(self, menu, vfs_file):
 
44
        # We can only cope with local files
 
45
        if vfs_file.get_uri_scheme() != 'file':
 
46
            return
 
47
 
 
48
        file = vfs_file.get_uri()
 
49
        try:
 
50
            tree, path = WorkingTree.open_containing(file)
 
51
        except NotBranchError:
 
52
            return
 
53
 
 
54
        #FIXME
 
55
 
 
56
        return
 
57
 
 
58
    def unignore_cb(self, menu, vfs_file):
 
59
        # We can only cope with local files
 
60
        if vfs_file.get_uri_scheme() != 'file':
 
61
            return
 
62
 
 
63
        file = vfs_file.get_uri()
 
64
        try:
 
65
            tree, path = WorkingTree.open_containing(file)
 
66
        except NotBranchError:
 
67
            return
 
68
 
 
69
        #FIXME
 
70
 
 
71
        return
 
72
 
 
73
    def diff_cb(self, menu, vfs_file):
 
74
        # We can only cope with local files
 
75
        if vfs_file.get_uri_scheme() != 'file':
 
76
            return
 
77
 
 
78
        file = vfs_file.get_uri()
 
79
        try:
 
80
            tree, path = WorkingTree.open_containing(file)
 
81
        except NotBranchError:
 
82
            return
 
83
 
 
84
        from bzrlib.plugins.gtk.diff import DiffWindow
 
85
        window = DiffWindow()
 
86
        window.set_diff(tree.branch.nick, tree, tree.branch.basis_tree())
 
87
        window.show()
 
88
 
 
89
        return
 
90
 
 
91
    def newtree_cb(self, menu, vfs_file):
 
92
        # We can only cope with local files
 
93
        if vfs_file.get_uri_scheme() != 'file':
 
94
            return
 
95
 
 
96
        file = vfs_file.get_uri()
 
97
 
 
98
        # We only want to continue here if we get a NotBranchError
 
99
        try:
 
100
            tree, path = WorkingTree.open_containing(file)
 
101
        except NotBranchError:
 
102
            BzrDir.create_standalone_workingtree(file)
 
103
 
 
104
    def remove_cb(self, menu, vfs_file):
 
105
        # We can only cope with local files
 
106
        if vfs_file.get_uri_scheme() != 'file':
 
107
            return
 
108
 
 
109
        file = vfs_file.get_uri()
 
110
        try:
 
111
            tree, path = WorkingTree.open_containing(file)
 
112
        except NotBranchError:
 
113
            return
 
114
 
 
115
        tree.remove(path)
 
116
 
 
117
    def annotate_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
        vis = cmd_gannotate()
 
125
        vis.run(file)
 
126
 
 
127
    def clone_cb(self, menu, vfs_file=None):
 
128
        # We can only cope with local files
 
129
        if vfs_file.get_uri_scheme() != 'file':
 
130
            return
 
131
 
 
132
        from bzrlib.plugins.gtk.branch import BranchDialog
 
133
        
 
134
        dialog = BranchDialog(vfs_file.get_name())
 
135
        response = dialog.run()
 
136
        if response != gtk.RESPONSE_NONE:
 
137
            dialog.hide()
 
138
            dialog.destroy()
 
139
 
 
140
    def commit_cb(self, menu, vfs_file=None):
 
141
        # We can only cope with local files
 
142
        if vfs_file.get_uri_scheme() != 'file':
 
143
            return
 
144
 
 
145
        file = vfs_file.get_uri()
 
146
        tree = None
 
147
        branch = None
 
148
        try:
 
149
            tree, path = WorkingTree.open_containing(file)
 
150
            branch = tree.branch
 
151
        except NotBranchError, e:
 
152
            path = e.path
 
153
            #return
 
154
        except NoWorkingTree, e:
 
155
            path = e.base
 
156
            try:
 
157
                (branch, path) = Branch.open_containing(path)
 
158
            except NotBranchError, e:
 
159
                path = e.path
 
160
 
 
161
        from bzrlib.plugins.gtk.commit import CommitDialog
 
162
        dialog = CommitDialog(tree, path)
 
163
        response = dialog.run()
 
164
        if response != gtk.RESPONSE_NONE:
 
165
            dialog.hide()
 
166
            dialog.destroy()
 
167
 
 
168
    def log_cb(self, menu, vfs_file):
 
169
        # We can only cope with local files
 
170
        if vfs_file.get_uri_scheme() != 'file':
 
171
            return
 
172
 
 
173
        file = vfs_file.get_uri()
 
174
 
 
175
        # We only want to continue here if we get a NotBranchError
 
176
        try:
 
177
            tree, path = WorkingTree.open_containing(file)
 
178
        except NotBranchError:
 
179
            return
 
180
 
 
181
        vis = cmd_visualise()
 
182
        vis.run(file)
 
183
 
 
184
        return
 
185
 
 
186
    def pull_cb(self, menu, vfs_file):
 
187
        # We can only cope with local files
 
188
        if vfs_file.get_uri_scheme() != 'file':
 
189
            return
 
190
 
 
191
        file = vfs_file.get_uri()
 
192
 
 
193
        # We only want to continue here if we get a NotBranchError
 
194
        try:
 
195
            tree, path = WorkingTree.open_containing(file)
 
196
        except NotBranchError:
 
197
            return
 
198
 
 
199
        from bzrlib.plugins.gtk.pull import PullDialog
 
200
        dialog = PullDialog(tree, path)
 
201
        dialog.display()
 
202
        gtk.main()
 
203
 
 
204
    def merge_cb(self, menu, vfs_file):
 
205
        # We can only cope with local files
 
206
        if vfs_file.get_uri_scheme() != 'file':
 
207
            return
 
208
 
 
209
        file = vfs_file.get_uri()
 
210
 
 
211
        # We only want to continue here if we get a NotBranchError
 
212
        try:
 
213
            tree, path = WorkingTree.open_containing(file)
 
214
        except NotBranchError:
 
215
            return
 
216
 
 
217
        from bzrlib.plugins.gtk.merge import MergeDialog
 
218
        dialog = MergeDialog(tree, path)
 
219
        dialog.display()
 
220
        gtk.main()
 
221
 
 
222
    def get_background_items(self, window, vfs_file):
 
223
        items = []
 
224
        file = vfs_file.get_uri()
 
225
 
 
226
        try:
 
227
            tree, path = WorkingTree.open_containing(file)
 
228
            disabled_flag = self.check_branch_enabled(tree.branch)
 
229
        except UnsupportedProtocol:
 
230
            return
 
231
        except NotBranchError:
 
232
            disabled_flag = self.check_branch_enabled()
 
233
            item = nautilus.MenuItem('BzrNautilus::newtree',
 
234
                                 'Make directory versioned',
 
235
                                 'Create new Bazaar tree in this folder')
 
236
            item.connect('activate', self.newtree_cb, vfs_file)
 
237
            items.append(item)
 
238
 
 
239
            item = nautilus.MenuItem('BzrNautilus::clone',
 
240
                                 'Checkout Bazaar branch',
 
241
                                 'Checkout Existing Bazaar Branch')
 
242
            item.connect('activate', self.clone_cb, vfs_file)
 
243
            items.append(item)
 
244
 
 
245
            return items
 
246
        except NoWorkingTree:
 
247
            return
 
248
        
 
249
        if disabled_flag == 'False':
 
250
            item = nautilus.MenuItem('BzrNautilus::enable',
 
251
                                     'Enable Bazaar Plugin for this Branch',
 
252
                                     'Enable Bazaar plugin for nautilus')
 
253
            item.connect('activate', self.toggle_integration, 'True', vfs_file)
 
254
            return item,
 
255
        else:
 
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)
 
260
            items.append(item)
 
261
 
 
262
        item = nautilus.MenuItem('BzrNautilus::log',
 
263
                             'Log',
 
264
                             'Show Bazaar history')
 
265
        item.connect('activate', self.log_cb, vfs_file)
 
266
        items.append(item)
 
267
 
 
268
        item = nautilus.MenuItem('BzrNautilus::pull',
 
269
                             'Pull',
 
270
                             'Pull from another branch')
 
271
        item.connect('activate', self.pull_cb, vfs_file)
 
272
        items.append(item)
 
273
 
 
274
        item = nautilus.MenuItem('BzrNautilus::merge',
 
275
                             'Merge',
 
276
                             'Merge from another branch')
 
277
        item.connect('activate', self.merge_cb, vfs_file)
 
278
        items.append(item)
 
279
 
 
280
        item = nautilus.MenuItem('BzrNautilus::commit',
 
281
                             'Commit',
 
282
                             'Commit Changes')
 
283
        item.connect('activate', self.commit_cb, vfs_file)
 
284
        items.append(item)
 
285
 
 
286
        return items
 
287
 
 
288
    def get_file_items(self, window, files):
 
289
        items = []
 
290
        
 
291
        wtfiles = {}
 
292
        for vfs_file in files:
 
293
            # We can only cope with local files
 
294
            if vfs_file.get_uri_scheme() != 'file':
 
295
                continue
 
296
 
 
297
            file = vfs_file.get_uri()
 
298
            try:
 
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():
 
304
                    continue
 
305
 
 
306
                if disabled_flag == 'False':
 
307
                    return
 
308
 
 
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)
 
313
                return item,
 
314
            except NoWorkingTree:
 
315
                continue
 
316
            # Refresh the list of filestatuses in the working tree
 
317
            if path not in wtfiles.keys():
 
318
                tree.lock_read()
 
319
                for rpath, file_class, kind, id, entry in tree.list_files():
 
320
                    wtfiles[rpath] = file_class
 
321
                tree.unlock()
 
322
                wtfiles[u''] = 'V'
 
323
 
 
324
            if wtfiles[path] == '?':
 
325
                item = nautilus.MenuItem('BzrNautilus::add',
 
326
                                     'Add',
 
327
                                     'Add as versioned file')
 
328
                item.connect('activate', self.add_cb, vfs_file)
 
329
                items.append(item)
 
330
 
 
331
                item = nautilus.MenuItem('BzrNautilus::ignore',
 
332
                                     'Ignore',
 
333
                                     'Ignore file for versioning')
 
334
                item.connect('activate', self.ignore_cb, vfs_file)
 
335
                items.append(item)
 
336
            elif wtfiles[path] == 'I':
 
337
                item = nautilus.MenuItem('BzrNautilus::unignore',
 
338
                                     'Unignore',
 
339
                                     'Unignore file for versioning')
 
340
                item.connect('activate', self.unignore_cb, vfs_file)
 
341
                items.append(item)
 
342
            elif wtfiles[path] == 'V':
 
343
                item = nautilus.MenuItem('BzrNautilus::log',
 
344
                                 'Log',
 
345
                                 'List changes')
 
346
                item.connect('activate', self.log_cb, vfs_file)
 
347
                items.append(item)
 
348
 
 
349
                item = nautilus.MenuItem('BzrNautilus::diff',
 
350
                                 'Diff',
 
351
                                 'Show differences')
 
352
                item.connect('activate', self.diff_cb, vfs_file)
 
353
                items.append(item)
 
354
 
 
355
                item = nautilus.MenuItem('BzrNautilus::remove',
 
356
                                     'Remove',
 
357
                                     'Remove this file from versioning')
 
358
                item.connect('activate', self.remove_cb, vfs_file)
 
359
                items.append(item)
 
360
 
 
361
                item = nautilus.MenuItem('BzrNautilus::annotate',
 
362
                             'Annotate',
 
363
                             'Annotate File Data')
 
364
                item.connect('activate', self.annotate_cb, vfs_file)
 
365
                items.append(item)
 
366
 
 
367
                item = nautilus.MenuItem('BzrNautilus::commit',
 
368
                             'Commit',
 
369
                             'Commit Changes')
 
370
                item.connect('activate', self.commit_cb, vfs_file)
 
371
                items.append(item)
 
372
 
 
373
        return items
 
374
 
 
375
    def get_columns(self):
 
376
        return nautilus.Column("BzrNautilus::bzr_status",
 
377
                               "bzr_status",
 
378
                               "Bzr Status",
 
379
                               "Version control status"),
 
380
 
 
381
    def update_file_info(self, file):
 
382
 
 
383
        if file.get_uri_scheme() != 'file':
 
384
            return
 
385
        
 
386
        try:
 
387
            tree, path = WorkingTree.open_containing(file.get_uri())
 
388
        except NotBranchError:
 
389
            return
 
390
        except NoWorkingTree:
 
391
            return   
 
392
 
 
393
        disabled_flag = self.check_branch_enabled(tree.branch)
 
394
        if disabled_flag == 'False':
 
395
            return
 
396
 
 
397
        emblem = None
 
398
        status = None
 
399
 
 
400
        if tree.has_filename(path):
 
401
            emblem = 'bzr-controlled'
 
402
            status = 'unchanged'
 
403
            id = tree.path2id(path)
 
404
 
 
405
            delta = tree.changes_from(tree.branch.basis_tree())
 
406
            if delta.touches_file_id(id):
 
407
                emblem = 'bzr-modified'
 
408
                status = 'modified'
 
409
            for f, _, _ in delta.added:
 
410
                if f == path:
 
411
                    emblem = 'bzr-added'
 
412
                    status = 'added'
 
413
 
 
414
            for of, f, _, _, _, _ in delta.renamed:
 
415
                if f == path:
 
416
                    status = 'renamed from %s' % f
 
417
 
 
418
        elif tree.branch.basis_tree().has_filename(path):
 
419
            emblem = 'bzr-removed'
 
420
            status = 'removed'
 
421
        else:
 
422
            # FIXME: Check for ignored files
 
423
            status = 'unversioned'
 
424
        
 
425
        if emblem is not None:
 
426
            file.add_emblem(emblem)
 
427
        file.add_string_attribute('bzr_status', status)
 
428
 
 
429
    def check_branch_enabled(self, branch=None):
 
430
        # Supports global disable, but there is currently no UI to do this
 
431
        config = GlobalConfig()
 
432
        disabled_flag = config.get_user_option('nautilus_integration')
 
433
        if disabled_flag != 'False':
 
434
            if branch is not None:
 
435
                config = branch.get_config()
 
436
                disabled_flag = config.get_user_option('nautilus_integration')
 
437
        return disabled_flag
 
438
 
 
439
    def toggle_integration(self, menu, action, vfs_file=None):
 
440
        try:
 
441
            tree, path = WorkingTree.open_containing(vfs_file.get_uri())
 
442
        except NotBranchError:
 
443
            return
 
444
        except NoWorkingTree:
 
445
            return
 
446
        branch = tree.branch
 
447
        if branch is None:
 
448
            config = GlobalConfig()
 
449
        else:
 
450
            config = branch.get_config()
 
451
        config.set_user_option('nautilus_integration', action)
 
452