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.workingtree import WorkingTree
16
from bzrlib.config import GlobalConfig
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, GObject, Nautilus
29
from bzrlib.controldir import ControlDir
30
from bzrlib.errors import (
34
from bzrlib.ignores import tree_ignores_add_patterns
35
from bzrlib.tree import InterTree
18
37
from bzrlib.plugin import load_plugins
21
from bzrlib.plugins.gtk.commands import cmd_gannotate, start_viz_window
23
print "Bazaar nautilus module initialized"
26
class BzrExtension(nautilus.MenuProvider, nautilus.ColumnProvider, nautilus.InfoProvider):
40
from bzrlib.plugins.gtk.i18n import _i18n
43
class BazaarExtension(Nautilus.MenuProvider, Nautilus.ColumnProvider,
44
Nautilus.InfoProvider, Nautilus.PropertyPageProvider,
45
Nautilus.LocationWidgetProvider, GObject.GObject):
46
"""Nautilus extension providing Bazaar integration."""
27
48
def __init__(self):
30
def add_cb(self, menu, vfs_file):
31
# We can only cope with local files
32
if vfs_file.get_uri_scheme() != 'file':
35
file = vfs_file.get_uri()
37
tree, path = WorkingTree.open_containing(file)
38
except NotBranchError:
52
def _open_bzrdir(cls, vfs_file):
53
uri = vfs_file.get_uri()
54
controldir, path = ControlDir.open_containing(uri)
55
return controldir, path
58
def _open_tree(cls, vfs_file):
59
controldir, path = cls._open_bzrdir(vfs_file)
60
return controldir.open_workingtree(), path
62
def add_cb(self, menu, tree, path):
45
def ignore_cb(self, menu, vfs_file):
46
# We can only cope with local files
47
if vfs_file.get_uri_scheme() != 'file':
50
file = vfs_file.get_uri()
52
tree, path = WorkingTree.open_containing(file)
53
except NotBranchError:
60
def unignore_cb(self, menu, vfs_file):
61
# We can only cope with local files
62
if vfs_file.get_uri_scheme() != 'file':
65
file = vfs_file.get_uri()
67
tree, path = WorkingTree.open_containing(file)
68
except NotBranchError:
75
def diff_cb(self, menu, vfs_file):
76
# We can only cope with local files
77
if vfs_file.get_uri_scheme() != 'file':
80
file = vfs_file.get_uri()
82
tree, path = WorkingTree.open_containing(file)
83
except NotBranchError:
65
def ignore_cb(self, menu, tree, path):
66
# We can only cope with local files
67
tree_ignores_add_patterns(tree, [path])
68
#FIXME: Add path to ignore file
70
def unignore_cb(self, menu, tree, path):
72
# We can only cope with local files
75
def diff_cb(self, menu, tree, path=None):
86
76
from bzrlib.plugins.gtk.diff import DiffWindow
87
77
window = DiffWindow()
88
78
window.set_diff(tree.branch._get_nick(local=True), tree,
89
79
tree.branch.basis_tree())
94
82
def newtree_cb(self, menu, vfs_file):
95
# We can only cope with local files
96
if vfs_file.get_uri_scheme() != 'file':
99
file = vfs_file.get_uri()
101
# We only want to continue here if we get a NotBranchError
103
tree, path = WorkingTree.open_containing(file)
104
except NotBranchError:
105
BzrDir.create_standalone_workingtree(file)
107
def remove_cb(self, menu, vfs_file):
108
# We can only cope with local files
109
if vfs_file.get_uri_scheme() != 'file':
112
file = vfs_file.get_uri()
114
tree, path = WorkingTree.open_containing(file)
115
except NotBranchError:
83
controldir, path = self._open_bzrdir(vfs_file)
84
controldir.create_workingtree()
86
def remove_cb(self, menu, tree, path):
120
def annotate_cb(self, menu, vfs_file):
121
# We can only cope with local files
122
if vfs_file.get_uri_scheme() != 'file':
125
file = vfs_file.get_uri()
127
vis = cmd_gannotate()
89
def annotate_cb(self, menu, tree, path, file_id):
90
from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
91
win = GAnnotateWindow()
93
win.annotate(tree, tree.branch, file_id)
130
96
def clone_cb(self, menu, vfs_file=None):
131
# We can only cope with local files
132
if vfs_file.get_uri_scheme() != 'file':
135
97
from bzrlib.plugins.gtk.branch import BranchDialog
98
controldir, path = self._open_bzrdir(vfs_file)
137
100
dialog = BranchDialog(vfs_file.get_name())
138
101
response = dialog.run()
139
if response != gtk.RESPONSE_NONE:
102
if response != Gtk.ResponseType.NONE:
143
def commit_cb(self, menu, vfs_file=None):
144
# We can only cope with local files
145
if vfs_file.get_uri_scheme() != 'file':
148
file = vfs_file.get_uri()
152
tree, path = WorkingTree.open_containing(file)
154
except NotBranchError, e:
157
except NoWorkingTree, e:
160
(branch, path) = Branch.open_containing(path)
161
except NotBranchError, e:
106
def commit_cb(self, menu, tree, path=None):
164
107
from bzrlib.plugins.gtk.commit import CommitDialog
165
108
dialog = CommitDialog(tree, path)
166
109
response = dialog.run()
167
if response != gtk.RESPONSE_NONE:
110
if response != Gtk.ResponseType.NONE:
171
def log_cb(self, menu, vfs_file):
172
# We can only cope with local files
173
if vfs_file.get_uri_scheme() != 'file':
176
file = vfs_file.get_uri()
178
# We only want to continue here if we get a NotBranchError
180
branch, path = Branch.open_containing(file)
181
except NotBranchError:
184
pp = start_viz_window(branch, [branch.last_revision()])
114
def log_cb(self, menu, controldir, path=None):
115
from bzrlib.plugins.gtk.viz import BranchWindow
116
branch = controldir.open_branch()
117
pp = BranchWindow(branch, [branch.last_revision()], None)
188
def pull_cb(self, menu, vfs_file):
189
# We can only cope with local files
190
if vfs_file.get_uri_scheme() != 'file':
193
file = vfs_file.get_uri()
195
# We only want to continue here if we get a NotBranchError
197
tree, path = WorkingTree.open_containing(file)
198
except NotBranchError:
121
def pull_cb(self, menu, controldir, path=None):
201
122
from bzrlib.plugins.gtk.pull import PullDialog
202
dialog = PullDialog(tree, path)
123
dialog = PullDialog(controldir.open_workingtree(), path)
206
def merge_cb(self, menu, vfs_file):
207
# We can only cope with local files
208
if vfs_file.get_uri_scheme() != 'file':
211
file = vfs_file.get_uri()
213
# We only want to continue here if we get a NotBranchError
215
tree, path = WorkingTree.open_containing(file)
216
except NotBranchError:
127
def merge_cb(self, menu, tree, path=None):
219
128
from bzrlib.plugins.gtk.merge import MergeDialog
220
129
dialog = MergeDialog(tree, path)
133
def create_tree_cb(self, menu, controldir):
134
controldir.create_workingtree()
224
136
def get_background_items(self, window, vfs_file):
226
file = vfs_file.get_uri()
229
tree, path = WorkingTree.open_containing(file)
230
disabled_flag = self.check_branch_enabled(tree.branch)
231
except UnsupportedProtocol:
138
controldir, path = self._open_bzrdir(vfs_file)
139
except NotBranchError:
142
branch = controldir.open_branch()
233
143
except NotBranchError:
234
disabled_flag = self.check_branch_enabled()
235
item = nautilus.MenuItem('BzrNautilus::newtree',
236
'Make directory versioned',
237
'Create new Bazaar tree in this folder')
145
item = Nautilus.MenuItem(name='BzrNautilus::newtree',
146
label='Make directory versioned',
147
tip='Create new Bazaar tree in this folder',
238
149
item.connect('activate', self.newtree_cb, vfs_file)
239
150
items.append(item)
241
item = nautilus.MenuItem('BzrNautilus::clone',
242
'Checkout Bazaar branch ...',
243
'Checkout Existing Bazaar Branch')
152
item = Nautilus.MenuItem(name='BzrNautilus::clone',
153
label='Checkout Bazaar branch ...',
154
tip='Checkout Existing Bazaar Branch',
244
156
item.connect('activate', self.clone_cb, vfs_file)
245
157
items.append(item)
162
nautilus_integration = self.check_branch_enabled(branch)
163
if not nautilus_integration:
164
item = Nautilus.MenuItem(name='BzrNautilus::enable',
165
label='Enable Bazaar Plugin for this Branch',
166
tip='Enable Bazaar plugin for nautilus',
168
item.connect('activate', self.toggle_integration, True, branch)
171
item = Nautilus.MenuItem(name='BzrNautilus::disable',
172
label='Disable Bazaar Plugin this Branch',
173
tip='Disable Bazaar plugin for nautilus',
175
item.connect('activate', self.toggle_integration, False, branch)
178
item = Nautilus.MenuItem(name='BzrNautilus::log',
180
tip='Show Bazaar history',
182
item.connect('activate', self.log_cb, controldir)
185
item = Nautilus.MenuItem(name='BzrNautilus::pull',
187
tip='Pull from another branch',
189
item.connect('activate', self.pull_cb, controldir)
193
tree = controldir.open_workingtree()
248
194
except NoWorkingTree:
251
if disabled_flag == 'False':
252
item = nautilus.MenuItem('BzrNautilus::enable',
253
'Enable Bazaar Plugin for this Branch',
254
'Enable Bazaar plugin for nautilus')
255
item.connect('activate', self.toggle_integration, 'True', vfs_file)
195
item = Nautilus.MenuItem(name='BzrNautilus::create_tree',
196
label='Create working tree...',
197
tip='Create a working tree for this branch',
199
item.connect('activate', self.create_tree_cb, controldir)
258
item = nautilus.MenuItem('BzrNautilus::disable',
259
'Disable Bazaar Plugin this Branch',
260
'Disable Bazaar plugin for nautilus')
261
item.connect('activate', self.toggle_integration, 'False', vfs_file)
264
item = nautilus.MenuItem('BzrNautilus::log',
266
'Show Bazaar history')
267
item.connect('activate', self.log_cb, vfs_file)
270
item = nautilus.MenuItem('BzrNautilus::pull',
272
'Pull from another branch')
273
item.connect('activate', self.pull_cb, vfs_file)
276
item = nautilus.MenuItem('BzrNautilus::merge',
278
'Merge from another branch')
279
item.connect('activate', self.merge_cb, vfs_file)
282
item = nautilus.MenuItem('BzrNautilus::commit',
285
item.connect('activate', self.commit_cb, vfs_file)
202
item = Nautilus.MenuItem(name='BzrNautilus::merge',
204
tip='Merge from another branch',
206
item.connect('activate', self.merge_cb, tree, path)
209
item = Nautilus.MenuItem(name='BzrNautilus::commit',
211
tip='Commit Changes',
213
item.connect('activate', self.commit_cb, tree, path)
218
def _get_file_menuitems(self, tree, intertree, path):
219
file_id = tree.path2id(path)
221
item = Nautilus.MenuItem(name='BzrNautilus::add',
223
tip='Add as versioned file',
225
item.connect('activate', self.add_cb, tree, path)
228
item = Nautilus.MenuItem(name='BzrNautilus::ignore',
230
tip='Ignore file for versioning',
232
item.connect('activate', self.ignore_cb, tree, path)
234
elif tree.is_ignored(path):
235
item = Nautilus.MenuItem(name='BzrNautilus::unignore',
237
tip='Unignore file for versioning',
239
item.connect('activate', self.unignore_cb, tree, path)
242
item = Nautilus.MenuItem(name='BzrNautilus::log',
246
item.connect('activate', self.log_cb, tree.bzrdir, path)
249
if not intertree.file_content_matches(file_id, file_id):
250
item = Nautilus.MenuItem(name='BzrNautilus::diff',
251
label='View Changes ...',
252
tip='Show differences',
254
item.connect('activate', self.diff_cb, tree, path)
257
item = Nautilus.MenuItem(name='BzrNautilus::commit',
259
tip='Commit Changes',
261
item.connect('activate', self.commit_cb, tree, path)
264
item = Nautilus.MenuItem(name='BzrNautilus::remove',
266
tip='Remove this file from versioning',
268
item.connect('activate', self.remove_cb, tree, path)
271
item = Nautilus.MenuItem(name='BzrNautilus::annotate',
272
label='Annotate ...',
273
tip='Annotate File Data',
275
item.connect('activate', self.annotate_cb, tree, path, file_id)
290
278
def get_file_items(self, window, files):
294
for vfs_file in files:
295
# We can only cope with local files
296
if vfs_file.get_uri_scheme() != 'file':
299
file = vfs_file.get_uri()
301
tree, path = WorkingTree.open_containing(file)
302
disabled_flag = self.check_branch_enabled(tree.branch)
303
except NotBranchError:
304
disabled_flag = self.check_branch_enabled()
305
if not vfs_file.is_directory():
283
for vfs_file in files:
284
controldir, path = self._open_bzrdir(vfs_file)
287
tree = trees[controldir.user_url]
290
tree = controldir.open_workingtree()
291
except NoWorkingTree:
293
trees[controldir.user_url] = tree
296
nautilus_integration = self.check_branch_enabled(tree.branch)
297
if not nautilus_integration:
308
if disabled_flag == 'False':
311
item = nautilus.MenuItem('BzrNautilus::newtree',
312
'Make directory versioned',
313
'Create new Bazaar tree in %s' % vfs_file.get_name())
314
item.connect('activate', self.newtree_cb, vfs_file)
316
except NoWorkingTree:
318
# Refresh the list of filestatuses in the working tree
319
if path not in wtfiles.keys():
321
for rpath, file_class, kind, id, entry in tree.list_files():
322
wtfiles[rpath] = file_class
300
intertree = InterTree.get(tree.basis_tree(), tree)
301
items.extend(list(self._get_file_menuitems(tree, intertree, path)))
303
for tree in trees.itervalues():
326
if wtfiles[path] == '?':
327
item = nautilus.MenuItem('BzrNautilus::add',
329
'Add as versioned file')
330
item.connect('activate', self.add_cb, vfs_file)
333
item = nautilus.MenuItem('BzrNautilus::ignore',
335
'Ignore file for versioning')
336
item.connect('activate', self.ignore_cb, vfs_file)
338
elif wtfiles[path] == 'I':
339
item = nautilus.MenuItem('BzrNautilus::unignore',
341
'Unignore file for versioning')
342
item.connect('activate', self.unignore_cb, vfs_file)
344
elif wtfiles[path] == 'V':
345
item = nautilus.MenuItem('BzrNautilus::log',
348
item.connect('activate', self.log_cb, vfs_file)
351
item = nautilus.MenuItem('BzrNautilus::diff',
354
item.connect('activate', self.diff_cb, vfs_file)
357
item = nautilus.MenuItem('BzrNautilus::remove',
359
'Remove this file from versioning')
360
item.connect('activate', self.remove_cb, vfs_file)
363
item = nautilus.MenuItem('BzrNautilus::annotate',
365
'Annotate File Data')
366
item.connect('activate', self.annotate_cb, vfs_file)
369
item = nautilus.MenuItem('BzrNautilus::commit',
372
item.connect('activate', self.commit_cb, vfs_file)
377
308
def get_columns(self):
378
return nautilus.Column("BzrNautilus::bzr_status",
381
"Version control status"),
383
def update_file_info(self, file):
385
if file.get_uri_scheme() != 'file':
389
tree, path = WorkingTree.open_containing(file.get_uri())
390
except NotBranchError:
392
except NoWorkingTree:
395
disabled_flag = self.check_branch_enabled(tree.branch)
396
if disabled_flag == 'False':
310
Nautilus.Column(name="BzrNautilus::bzr_status",
311
attribute="bzr_status",
313
description="Version control status"),
314
Nautilus.Column(name="BzrNautilus::bzr_revision",
315
attribute="bzr_revision",
317
description="Last change revision"),
320
def _file_summary(self, tree, basis_tree, intertree, path):
402
id = tree.path2id(path)
324
file_id = tree.path2id(path)
404
326
if tree.is_ignored(path):
405
327
status = 'ignored'
406
328
emblem = 'bzr-ignored'
408
330
status = 'unversioned'
410
elif tree.has_filename(path):
411
emblem = 'bzr-controlled'
414
delta = tree.changes_from(tree.branch.basis_tree())
415
if delta.touches_file_id(id):
416
emblem = 'bzr-modified'
418
for f, _, _ in delta.added:
331
file_revision = "N/A"
332
elif tree.has_filename(path): # Still present
333
if not intertree.file_content_matches(file_id, file_id):
334
if not basis_tree.has_id(file_id):
420
335
emblem = 'bzr-added'
423
for of, f, _, _, _, _ in delta.renamed:
425
status = 'renamed from %s' % f
427
elif tree.branch.basis_tree().has_filename(path):
337
file_revision = "new file"
338
elif basis_tree.path2id(file_id) != path:
339
status = 'bzr-renamed'
340
status = 'renamed from %s' % basis_tree.path2id(file_id)
342
emblem = 'bzr-modified'
345
emblem = 'bzr-controlled'
347
elif basis_tree.has_filename(path):
428
348
emblem = 'bzr-removed'
429
349
status = 'removed'
431
351
# FIXME: Check for ignored files
432
352
status = 'unversioned'
434
if emblem is not None:
435
file.add_emblem(emblem)
436
file.add_string_attribute('bzr_status', status)
438
def check_branch_enabled(self, branch=None):
353
return (status, emblem, file_revision)
355
def update_file_info(self, vfs_file):
357
controldir, path = self._open_bzrdir(vfs_file)
358
except NotBranchError:
362
tree = controldir.open_workingtree()
363
except NoWorkingTree:
368
nautilus_integration = self.check_branch_enabled(tree.branch)
369
if not nautilus_integration:
372
basis_tree = tree.basis_tree()
373
intertree = InterTree.get(basis_tree, tree)
375
basis_tree.lock_read()
377
(status, emblem, file_revision) = self._file_summary(tree, basis_tree, intertree, path)
380
if emblem is not None:
381
vfs_file.add_emblem(emblem)
382
vfs_file.add_string_attribute('bzr_status', status)
383
vfs_file.add_string_attribute('bzr_revision', file_revision)
387
def check_branch_enabled(self, branch):
439
388
# Supports global disable, but there is currently no UI to do this
440
config = GlobalConfig()
441
disabled_flag = config.get_user_option('nautilus_integration')
442
if disabled_flag != 'False':
443
if branch is not None:
444
config = branch.get_config()
445
disabled_flag = config.get_user_option('nautilus_integration')
448
def toggle_integration(self, menu, action, vfs_file=None):
389
config = branch.get_config_stack()
390
return config.get("nautilus_integration")
392
def toggle_integration(self, menu, action, branch):
393
config = branch.get_config_stack()
394
config.set("nautilus_integration", action)
396
def get_property_pages(self, files):
398
for vfs_file in files:
400
controldir, path = self._open_bzrdir(vfs_file)
401
except NotBranchError:
405
tree = controldir.open_workingtree()
406
except NoWorkingTree:
411
file_id = tree.path2id(path)
412
pages.append(PropertyPageFile(tree, file_id, path))
413
pages.append(PropertyPageBranch(tree.branch))
418
def get_widget(self, uri, window):
419
controldir, path = ControlDir.open_containing(uri)
450
tree, path = WorkingTree.open_containing(vfs_file.get_uri())
451
except NotBranchError:
421
tree = controldir.open_workingtree()
453
422
except NoWorkingTree:
457
config = GlobalConfig()
459
config = branch.get_config()
460
config.set_user_option('nautilus_integration', action)
424
ret = Gtk.HBox(False, 4)
425
text = 'This is a Bazaar working tree. '
426
get_shelf_manager = getattr(tree, 'get_shelf_manager', None)
427
if get_shelf_manager is not None:
428
manager = get_shelf_manager()
429
shelves = manager.active_shelves()
430
if len(shelves) == 0:
432
elif len(shelves) == 1:
433
text += '1 shelf exists. '
435
text += '%d shelf exists. ' % len(shelves)
436
label = Gtk.Label(text)
438
ret.pack_start(label, True, True, 0)
443
class PropertyPageFile(Nautilus.PropertyPage):
445
def __init__(self, tree, file_id, path):
447
self.file_id = file_id
449
label = Gtk.Label('File Version')
452
table = self._create_table()
454
super(PropertyPageFile, self).__init__(label=label,
455
name="BzrNautilus::file_page", page=table)
457
def _create_table(self):
458
table = Gtk.Table(homogeneous=False, columns=2, rows=3)
460
table.attach(Gtk.Label(_i18n('File id:')), 0, 1, 0, 1)
461
table.attach(Gtk.Label(self.file_id), 1, 2, 0, 1)
463
table.attach(Gtk.Label(_i18n('SHA1Sum:')), 0, 1, 1, 2)
464
table.attach(Gtk.Label(self.tree.get_file_sha1(self.file_id, self.path)), 1, 1, 1, 2)
466
basis_tree = self.tree.revision_tree(self.tree.last_revision())
467
last_revision = basis_tree.get_file_revision(self.file_id)
469
table.attach(Gtk.Label(_i18n('Last Change Revision:')), 0, 1, 2, 3)
470
revno = ".".join([str(x) for x in
471
self.tree.branch.revision_id_to_dotted_revno(last_revision)])
472
table.attach(Gtk.Label(revno), 1, 1, 2, 3)
474
table.attach(Gtk.Label(_i18n('Last Change Author:')), 0, 1, 3, 4)
475
rev = self.tree.branch.repository.get_revision(last_revision)
476
table.attach(Gtk.Label("\n".join(rev.get_apparent_authors())), 1, 1, 3, 4)
482
class PropertyPageBranch(Nautilus.PropertyPage):
484
def __init__(self, branch):
486
label = Gtk.Label('Branch')
489
table = self._create_table()
491
super(PropertyPageBranch, self).__init__(label=label,
492
name="BzrNautilus::branch_page", page=table)
494
def _create_location_entry(self, get_location, set_location):
495
location = get_location()
497
if location is not None:
498
ret.set_text(location)
501
def _create_table(self):
502
table = Gtk.Table(homogeneous=False, columns=2, rows=6)
504
self._push_location_entry = self._create_location_entry(
505
self.branch.get_push_location, self.branch.set_push_location)
506
self._parent_location_entry = self._create_location_entry(
507
self.branch.get_parent, self.branch.set_parent)
508
self._bound_location_entry = self._create_location_entry(
509
self.branch.get_bound_location, self.branch.set_bound_location)
510
self._public_location_entry = self._create_location_entry(
511
self.branch.get_public_branch, self.branch.set_public_branch)
512
self._submit_location_entry = self._create_location_entry(
513
self.branch.get_submit_branch, self.branch.set_submit_branch)
515
table.attach(Gtk.Label(_i18n('Push location:')), 0, 1, 0, 1)
516
table.attach(self._push_location_entry, 1, 2, 0, 1)
518
table.attach(Gtk.Label(_i18n('Parent location:')), 0, 1, 1, 2)
519
table.attach(self._parent_location_entry, 1, 1, 1, 2)
521
table.attach(Gtk.Label(_i18n('Bound location:')), 0, 1, 2, 3)
522
table.attach(self._bound_location_entry, 1, 1, 2, 3)
524
table.attach(Gtk.Label(_i18n('Public location:')), 0, 1, 3, 4)
525
table.attach(self._public_location_entry, 1, 1, 3, 4)
527
table.attach(Gtk.Label(_i18n('Submit location:')), 0, 1, 4, 5)
528
table.attach(self._submit_location_entry, 1, 1, 4, 5)
530
self._append_revisions_only = Gtk.CheckButton(_i18n('Append revisions only'))
531
value = self.branch.get_append_revisions_only()
534
self._append_revisions_only.set_active(value)
535
table.attach(self._append_revisions_only, 0, 2, 5, 6)