38
34
from bzrlib.branch import Branch
39
import bzrlib.errors as bzrerrors
40
from bzrlib.lazy_import import lazy_import
41
from bzrlib.ui import ui_factory
35
import bzrlib.errors as errors
42
36
from bzrlib.workingtree import WorkingTree
44
from bzrlib.plugins.gtk import _i18n
45
from bzrlib.plugins.gtk.dialog import error_dialog, info_dialog, warning_dialog
46
from bzrlib.plugins.gtk.errors import show_bzr_error
38
from dialog import error_dialog, info_dialog
39
from errors import show_bzr_error
47
40
from guifiles import GLADEFILENAME
49
from bzrlib.plugins.gtk.diff import DiffWindow
50
lazy_import(globals(), """
51
from bzrlib.plugins.gtk.viz import branchwin
53
from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
54
from bzrlib.plugins.gtk.annotate.config import GAnnotateConfig
55
from bzrlib.plugins.gtk.commit import CommitDialog
56
from bzrlib.plugins.gtk.conflicts import ConflictsDialog
57
from bzrlib.plugins.gtk.initialize import InitDialog
58
from bzrlib.plugins.gtk.push import PushDialog
59
from bzrlib.plugins.gtk.revbrowser import RevisionBrowser
62
""" Display the AboutDialog. """
63
from bzrlib.plugins.gtk import __version__
64
from bzrlib.plugins.gtk.olive.guifiles import GLADEFILENAME
66
# Load AboutDialog description
67
dglade = gtk.glade.XML(GLADEFILENAME, 'aboutdialog')
68
dialog = dglade.get_widget('aboutdialog')
71
dialog.set_version(__version__)
72
dialog.set_authors([ _i18n("Lead Developer:"),
73
"Szilveszter Farkas <szilveszter.farkas@gmail.com>",
74
_i18n("Contributors:"),
75
"Jelmer Vernooij <jelmer@samba.org>",
76
"Mateusz Korniak <mateusz.korniak@ant.gliwice.pl>",
77
"Gary van der Merwe <garyvdm@gmail.com>" ])
78
dialog.set_artists([ "Simon Pascal Klein <klepas@klepas.org>",
79
"Jakub Steiner <jimmac@novell.com>" ])
42
# import this classes only once
44
from bzrlib.plugins.gtk.viz.diffwin import DiffWindow
45
from bzrlib.plugins.gtk.viz.branchwin import BranchWindow
46
from bzrlib.plugins.gtk.annotate.gannotate import GAnnotateWindow
47
from bzrlib.plugins.gtk.annotate.config import GAnnotateConfig
49
# olive+bzr-gtk not installed. try to import from sources
50
path = os.path.dirname(os.path.dirname(__file__))
51
if path not in sys.path:
53
from viz.diffwin import DiffWindow
54
from viz.branchwin import BranchWindow
55
from annotate.gannotate import GAnnotateWindow
56
from annotate.config import GAnnotateConfig
86
60
""" The main Olive GTK frontend class. This is called when launching the
106
83
# Get some important menu items
107
84
self.menuitem_add_files = self.toplevel.get_widget('menuitem_add_files')
108
85
self.menuitem_remove_files = self.toplevel.get_widget('menuitem_remove_file')
109
self.menuitem_file_bookmark = self.toplevel.get_widget('menuitem_file_bookmark')
110
86
self.menuitem_file_make_directory = self.toplevel.get_widget('menuitem_file_make_directory')
111
87
self.menuitem_file_rename = self.toplevel.get_widget('menuitem_file_rename')
112
88
self.menuitem_file_move = self.toplevel.get_widget('menuitem_file_move')
113
89
self.menuitem_file_annotate = self.toplevel.get_widget('menuitem_file_annotate')
114
90
self.menuitem_view_show_hidden_files = self.toplevel.get_widget('menuitem_view_show_hidden_files')
115
self.menuitem_view_show_ignored_files = self.toplevel.get_widget('menuitem_view_show_ignored_files')
116
91
self.menuitem_branch = self.toplevel.get_widget('menuitem_branch')
117
92
self.menuitem_branch_init = self.toplevel.get_widget('menuitem_branch_initialize')
118
93
self.menuitem_branch_get = self.toplevel.get_widget('menuitem_branch_get')
119
94
self.menuitem_branch_checkout = self.toplevel.get_widget('menuitem_branch_checkout')
120
95
self.menuitem_branch_pull = self.toplevel.get_widget('menuitem_branch_pull')
121
96
self.menuitem_branch_push = self.toplevel.get_widget('menuitem_branch_push')
122
self.menuitem_branch_update = self.toplevel.get_widget('menuitem_branch_update')
123
self.menuitem_branch_revert = self.toplevel.get_widget('menuitem_branch_revert')
124
97
self.menuitem_branch_merge = self.toplevel.get_widget('menuitem_branch_merge')
125
98
self.menuitem_branch_commit = self.toplevel.get_widget('menuitem_branch_commit')
126
self.menuitem_branch_tags = self.toplevel.get_widget('menuitem_branch_tags')
127
99
self.menuitem_branch_status = self.toplevel.get_widget('menuitem_branch_status')
128
100
self.menuitem_branch_missing = self.toplevel.get_widget('menuitem_branch_missing_revisions')
129
self.menuitem_branch_conflicts = self.toplevel.get_widget('menuitem_branch_conflicts')
130
101
self.menuitem_stats = self.toplevel.get_widget('menuitem_stats')
131
102
self.menuitem_stats_diff = self.toplevel.get_widget('menuitem_stats_diff')
132
103
self.menuitem_stats_log = self.toplevel.get_widget('menuitem_stats_log')
163
122
"on_about_activate": self.on_about_activate,
164
123
"on_menuitem_add_files_activate": self.on_menuitem_add_files_activate,
165
124
"on_menuitem_remove_file_activate": self.on_menuitem_remove_file_activate,
166
"on_menuitem_file_bookmark_activate": self.on_menuitem_file_bookmark_activate,
167
125
"on_menuitem_file_make_directory_activate": self.on_menuitem_file_make_directory_activate,
168
126
"on_menuitem_file_move_activate": self.on_menuitem_file_move_activate,
169
127
"on_menuitem_file_rename_activate": self.on_menuitem_file_rename_activate,
170
128
"on_menuitem_file_annotate_activate": self.on_menuitem_file_annotate_activate,
171
129
"on_menuitem_view_show_hidden_files_activate": self.on_menuitem_view_show_hidden_files_activate,
172
"on_menuitem_view_show_ignored_files_activate": self.on_menuitem_view_show_ignored_files_activate,
173
130
"on_menuitem_view_refresh_activate": self.on_menuitem_view_refresh_activate,
174
131
"on_menuitem_branch_initialize_activate": self.on_menuitem_branch_initialize_activate,
175
132
"on_menuitem_branch_get_activate": self.on_menuitem_branch_get_activate,
176
133
"on_menuitem_branch_checkout_activate": self.on_menuitem_branch_checkout_activate,
177
"on_menuitem_branch_revert_activate": self.on_menuitem_branch_revert_activate,
178
134
"on_menuitem_branch_merge_activate": self.on_menuitem_branch_merge_activate,
179
135
"on_menuitem_branch_commit_activate": self.on_menuitem_branch_commit_activate,
180
136
"on_menuitem_branch_push_activate": self.on_menuitem_branch_push_activate,
181
137
"on_menuitem_branch_pull_activate": self.on_menuitem_branch_pull_activate,
182
"on_menuitem_branch_update_activate": self.on_menuitem_branch_update_activate,
183
"on_menuitem_branch_tags_activate": self.on_menuitem_branch_tags_activate,
184
138
"on_menuitem_branch_status_activate": self.on_menuitem_branch_status_activate,
185
139
"on_menuitem_branch_missing_revisions_activate": self.on_menuitem_branch_missing_revisions_activate,
186
"on_menuitem_branch_conflicts_activate": self.on_menuitem_branch_conflicts_activate,
187
140
"on_menuitem_stats_diff_activate": self.on_menuitem_stats_diff_activate,
188
141
"on_menuitem_stats_log_activate": self.on_menuitem_stats_log_activate,
189
142
"on_menuitem_stats_infos_activate": self.on_menuitem_stats_infos_activate,
194
147
"on_toolbutton_commit_clicked": self.on_menuitem_branch_commit_activate,
195
148
"on_toolbutton_pull_clicked": self.on_menuitem_branch_pull_activate,
196
149
"on_toolbutton_push_clicked": self.on_menuitem_branch_push_activate,
197
"on_toolbutton_update_clicked": self.on_menuitem_branch_update_activate,
198
150
"on_treeview_right_button_press_event": self.on_treeview_right_button_press_event,
199
151
"on_treeview_right_row_activated": self.on_treeview_right_row_activated,
200
152
"on_treeview_left_button_press_event": self.on_treeview_left_button_press_event,
201
"on_treeview_left_button_release_event": self.on_treeview_left_button_release_event,
202
"on_treeview_left_row_activated": self.on_treeview_left_row_activated,
203
"on_button_location_up_clicked": self.on_button_location_up_clicked,
204
"on_button_location_jump_clicked": self.on_button_location_jump_clicked,
205
"on_entry_location_key_press_event": self.on_entry_location_key_press_event,
206
"on_checkbutton_history_toggled": self.on_checkbutton_history_toggled,
207
"on_entry_history_revno_key_press_event": self.on_entry_history_revno_key_press_event,
208
"on_button_history_browse_clicked": self.on_button_history_browse_clicked
153
"on_treeview_left_row_activated": self.on_treeview_left_row_activated }
211
155
# Connect the signals to the handlers
212
156
self.toplevel.signal_autoconnect(dic)
243
187
# Apply menu state
244
188
self.menuitem_view_show_hidden_files.set_active(self.pref.get_preference('dotted_files', 'bool'))
245
self.menuitem_view_show_ignored_files.set_active(self.pref.get_preference('ignored_files', 'bool'))
247
# We're starting local
249
self.remote_branch = None
250
self.remote_path = None
251
self.remote_revision = None
253
190
self.set_path(os.getcwd())
254
191
self._load_right()
256
193
self._just_started = False
258
def set_path(self, path, force_remote=False):
195
def set_path(self, path):
259
197
self.notbranch = False
262
# Forcing remote mode (reading data from inventory)
263
self._show_stock_image(gtk.STOCK_DISCONNECT)
265
br = Branch.open_containing(path)[0]
266
except bzrerrors.NotBranchError:
267
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
268
self.check_history.set_active(False)
269
self.check_history.set_sensitive(False)
271
except bzrerrors.UnsupportedProtocol:
272
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
273
self.check_history.set_active(False)
274
self.check_history.set_sensitive(False)
277
self._show_stock_image(gtk.STOCK_CONNECT)
282
self.remote_branch, self.remote_path = Branch.open_containing(path)
284
if self.remote_revision is None:
285
self.remote_revision = self.remote_branch.last_revision()
287
self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
289
if len(self.remote_path) == 0:
290
self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
292
for (name, type) in self.remote_entries:
293
if name == self.remote_path:
294
self.remote_parent = type.file_id
297
if not path.endswith('/'):
300
if self.remote_branch.base == path:
301
self.button_location_up.set_sensitive(False)
303
self.button_location_up.set_sensitive(True)
305
if os.path.isdir(path):
306
self.image_location_error.destroy()
311
self.wt, self.wtpath = WorkingTree.open_containing(path)
312
except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
313
self.notbranch = True
315
# If we're in the root, we cannot go up anymore
316
if sys.platform == 'win32':
317
drive, tail = os.path.splitdrive(path)
318
if tail in ('', '/', '\\'):
319
self.button_location_up.set_sensitive(False)
321
self.button_location_up.set_sensitive(True)
324
self.button_location_up.set_sensitive(False)
326
self.button_location_up.set_sensitive(True)
327
elif not os.path.isfile(path):
328
# Doesn't seem to be a file nor a directory, trying to open a
330
self._show_stock_image(gtk.STOCK_DISCONNECT)
332
br = Branch.open_containing(path)[0]
333
except bzrerrors.NotBranchError:
334
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
335
self.check_history.set_active(False)
336
self.check_history.set_sensitive(False)
338
except bzrerrors.UnsupportedProtocol:
339
self._show_stock_image(gtk.STOCK_DIALOG_ERROR)
340
self.check_history.set_active(False)
341
self.check_history.set_sensitive(False)
344
self._show_stock_image(gtk.STOCK_CONNECT)
349
self.remote_branch, self.remote_path = Branch.open_containing(path)
351
if self.remote_revision is None:
352
self.remote_revision = self.remote_branch.last_revision()
354
self.remote_entries = self.remote_branch.repository.get_inventory(self.remote_revision).entries()
356
if len(self.remote_path) == 0:
357
self.remote_parent = self.remote_branch.repository.get_inventory(self.remote_branch.last_revision()).iter_entries_by_dir().next()[1].file_id
359
for (name, type) in self.remote_entries:
360
if name == self.remote_path:
361
self.remote_parent = type.file_id
364
if not path.endswith('/'):
367
if self.remote_branch.base == path:
368
self.button_location_up.set_sensitive(False)
370
self.button_location_up.set_sensitive(True)
373
self.check_history.set_active(False)
374
self.check_history.set_sensitive(False)
376
self.check_history.set_sensitive(True)
200
self.wt, self.wtpath = WorkingTree.open_containing(self.path)
201
except (errors.NotBranchError, errors.NoWorkingTree):
202
self.notbranch = True
378
204
self.statusbar.push(self.context_id, path)
379
self.entry_location.set_text(path)
383
206
def get_path(self):
388
if len(self.remote_path) > 0:
389
return self.remote_branch.base + self.remote_path + '/'
391
return self.remote_branch.base
393
209
def on_about_activate(self, widget):
210
from dialog import about
396
def on_button_history_browse_clicked(self, widget):
397
""" Browse for revision button handler. """
399
br = self.remote_branch
403
revb = RevisionBrowser(br, self.window)
404
response = revb.run()
405
if response != gtk.RESPONSE_NONE:
408
if response == gtk.RESPONSE_OK:
409
if revb.selected_revno is not None:
410
self.entry_history.set_text(revb.selected_revno)
414
def on_button_location_jump_clicked(self, widget):
415
""" Location Jump button handler. """
416
location = self.entry_location.get_text()
418
if self.set_path(location):
421
def on_button_location_up_clicked(self, widget):
422
""" Location Up button handler. """
425
self.set_path(os.path.split(self.get_path())[0])
429
newpath = delim.join(self.get_path().split(delim)[:-2])
431
self.set_path(newpath)
435
def on_checkbutton_history_toggled(self, widget):
436
""" History Mode toggle handler. """
437
if self.check_history.get_active():
438
# History Mode activated
439
self.entry_history.set_sensitive(True)
440
self.button_history.set_sensitive(True)
442
# History Mode deactivated
443
self.entry_history.set_sensitive(False)
444
self.button_history.set_sensitive(False)
447
def on_entry_history_revno_key_press_event(self, widget, event):
448
""" Key pressed handler for the history entry. """
449
if event.keyval == gtk.gdk.keyval_from_name('Return') or event.keyval == gtk.gdk.keyval_from_name('KP_Enter'):
450
# Return was hit, so we have to load that specific revision
451
# Emulate being remote, so inventory should be used
452
path = self.get_path()
455
self.remote_branch = self.wt.branch
457
revno = int(self.entry_history.get_text())
458
self.remote_revision = self.remote_branch.get_rev_id(revno)
459
if self.set_path(path, True):
462
def on_entry_location_key_press_event(self, widget, event):
463
""" Key pressed handler for the location entry. """
464
if event.keyval == gtk.gdk.keyval_from_name('Return') or event.keyval == gtk.gdk.keyval_from_name('KP_Enter'):
465
# Return was hit, so we have to jump
466
self.on_button_location_jump_clicked(widget)
468
213
def on_menuitem_add_files_activate(self, widget):
469
214
""" Add file(s)... menu handler. """
470
215
from add import OliveAdd
474
219
def on_menuitem_branch_get_activate(self, widget):
475
220
""" Branch/Get... menu handler. """
476
from bzrlib.plugins.gtk.branch import BranchDialog
479
branch = BranchDialog(os.getcwd(), self.window, self.remote_branch.base)
481
branch = BranchDialog(self.get_path(), self.window)
482
response = branch.run()
483
if response != gtk.RESPONSE_NONE:
486
if response == gtk.RESPONSE_OK:
221
from branch import BranchDialog
222
branch = BranchDialog(self.get_path())
491
225
def on_menuitem_branch_checkout_activate(self, widget):
492
226
""" Branch/Checkout... menu handler. """
493
from bzrlib.plugins.gtk.checkout import CheckoutDialog
496
checkout = CheckoutDialog(os.getcwd(), self.window, self.remote_branch.base)
498
checkout = CheckoutDialog(self.get_path(), self.window)
499
response = checkout.run()
500
if response != gtk.RESPONSE_NONE:
503
if response == gtk.RESPONSE_OK:
227
from checkout import OliveCheckout
228
checkout = OliveCheckout(self.get_path())
509
231
def on_menuitem_branch_commit_activate(self, widget):
510
232
""" Branch/Commit... menu handler. """
511
# def __init__(self, wt, wtpath, notbranch, selected=None, parent=None):
512
selected = self.get_selected_right()
514
selected = os.path.join(self.wtpath, selected)
515
commit = CommitDialog(wt=self.wt,
233
from commit import CommitDialog
234
commit = CommitDialog(self.wt, self.wtpath, self.notbranch, self.get_selected_right(), self.window)
519
235
response = commit.run()
520
236
if response != gtk.RESPONSE_NONE:
528
def on_menuitem_branch_conflicts_activate(self, widget):
529
""" Branch/Conflicts... menu handler. """
530
conflicts = ConflictsDialog(self.wt, self.window)
531
response = conflicts.run()
532
if response != gtk.RESPONSE_NONE:
535
244
def on_menuitem_branch_merge_activate(self, widget):
536
245
""" Branch/Merge... menu handler. """
537
from bzrlib.plugins.gtk.merge import MergeDialog
246
from merge import MergeDialog
539
248
if self.check_for_changes():
540
error_dialog(_i18n('There are local changes in the branch'),
541
_i18n('Please commit or revert the changes before merging.'))
249
error_dialog(_('There are local changes in the branch'),
250
_('Please commit or revert the changes before merging.'))
543
parent_branch_path = self.wt.branch.get_parent()
544
merge = MergeDialog(self.wt, self.wtpath,default_branch_path=parent_branch_path )
252
merge = MergeDialog(self.wt, self.wtpath)
548
255
def on_menuitem_branch_missing_revisions_activate(self, widget):
549
256
""" Branch/Missing revisions menu handler. """
551
from bzrlib.missing import find_unmerged, iter_log_revisions
553
257
local_branch = self.wt.branch
554
parent_branch_path = local_branch.get_parent()
555
if parent_branch_path is None:
556
error_dialog(_i18n('Parent location is unknown'),
557
_i18n('Cannot determine missing revisions if no parent location is known.'))
259
other_branch = local_branch.get_parent()
260
if other_branch is None:
261
error_dialog(_('Parent location is unknown'),
262
_('Cannot determine missing revisions if no parent location is known.'))
560
parent_branch = Branch.open(parent_branch_path)
562
if parent_branch.base == local_branch.base:
563
parent_branch = local_branch
565
local_extra, remote_extra = find_unmerged(local_branch,parent_branch)
567
if local_extra or remote_extra:
569
## def log_revision_one_line_text(log_revision):
570
## """ Generates one line description of log_revison ended with end of line."""
571
## revision = log_revision.rev
572
## txt = "- %s (%s)\n" % (revision.get_summary(), revision.committer, )
573
## txt = txt.replace("<"," ") # Seems < > chars are expected to be xml tags ...
574
## txt = txt.replace(">"," ")
579
dlg_txt += _i18n('%d local extra revision(s). \n') % (len(local_extra),)
580
## NOTE: We do not want such ugly info about missing revisions
581
## Revision Browser should be used there
582
## max_revisions = 10
583
## for log_revision in iter_log_revisions(local_extra, local_branch.repository, verbose=1):
584
## dlg_txt += log_revision_one_line_text(log_revision)
585
## if max_revisions <= 0:
586
## dlg_txt += _i18n("more ... \n")
588
## max_revisions -= 1
591
dlg_txt += _i18n('%d local missing revision(s).\n') % (len(remote_extra),)
592
## max_revisions = 10
593
## for log_revision in iter_log_revisions(remote_extra, parent_branch.repository, verbose=1):
594
## dlg_txt += log_revision_one_line_text(log_revision)
595
## if max_revisions <= 0:
596
## dlg_txt += _i18n("more ... \n")
598
## max_revisions -= 1
600
info_dialog(_i18n('There are missing revisions'),
265
remote_branch = Branch.open(other_branch)
267
if remote_branch.base == local_branch.base:
268
remote_branch = local_branch
270
ret = len(local_branch.missing_revisions(remote_branch))
273
info_dialog(_('There are missing revisions'),
274
_('%d revision(s) missing.') % ret)
603
info_dialog(_i18n('Local branch up to date'),
604
_i18n('There are no missing revisions.'))
276
info_dialog(_('Local branch up to date'),
277
_('There are no missing revisions.'))
607
280
def on_menuitem_branch_pull_activate(self, widget):
619
292
if branch_to.get_parent() is None:
620
293
branch_to.set_parent(branch_from.base)
295
#old_rh = branch_to.revision_history()
296
#if tree_to is not None:
297
# tree_to.pull(branch_from)
299
# branch_to.pull(branch_from)
622
300
ret = branch_to.pull(branch_from)
624
info_dialog(_i18n('Pull successful'), _i18n('%d revision(s) pulled.') % ret)
627
def on_menuitem_branch_update_activate(self, widget):
628
""" Brranch/checkout update menu handler. """
630
ret = self.wt.update()
631
conflicts = self.wt.conflicts()
633
info_dialog(_i18n('Update successful but conflicts generated'), _i18n('Number of conflicts generated: %d.') % (len(conflicts),) )
635
info_dialog(_i18n('Update successful'), _i18n('No conflicts generated.') )
302
info_dialog(_('Pull successful'), _('%d revision(s) pulled.') % ret)
637
304
def on_menuitem_branch_push_activate(self, widget):
638
305
""" Branch/Push... menu handler. """
639
push = PushDialog(repository=None,revid=None,branch=self.wt.branch, parent=self.window)
640
response = push.run()
641
if response != gtk.RESPONSE_NONE:
645
def on_menuitem_branch_revert_activate(self, widget):
646
""" Branch/Revert all changes menu handler. """
647
ret = self.wt.revert([])
649
warning_dialog(_i18n('Conflicts detected'),
650
_i18n('Please have a look at the working tree before continuing.'))
652
info_dialog(_i18n('Revert successful'),
653
_i18n('All files reverted to last revision.'))
306
from push import OlivePush
307
push = OlivePush(self.wt.branch)
656
310
def on_menuitem_branch_status_activate(self, widget):
657
311
""" Branch/Status... menu handler. """
658
from bzrlib.plugins.gtk.status import StatusDialog
659
status = StatusDialog(self.wt, self.wtpath)
660
response = status.run()
661
if response != gtk.RESPONSE_NONE:
312
from status import OliveStatus
313
status = OliveStatus(self.wt, self.wtpath)
664
317
def on_menuitem_branch_initialize_activate(self, widget):
665
318
""" Initialize current directory. """
666
init = InitDialog(self.path, self.window)
667
response = init.run()
668
if response != gtk.RESPONSE_NONE:
671
if response == gtk.RESPONSE_OK:
676
def on_menuitem_branch_tags_activate(self, widget):
677
""" Branch/Tags... menu handler. """
678
from bzrlib.plugins.gtk.tags import TagsWindow
680
window = TagsWindow(self.wt.branch, self.window)
319
import bzrlib.bzrdir as bzrdir
321
if not os.path.exists(self.path):
325
existing_bzrdir = bzrdir.BzrDir.open(self.path)
326
except errors.NotBranchError:
327
bzrdir.BzrDir.create_branch_convenience(self.path)
682
window = TagsWindow(self.remote_branch, self.window)
329
if existing_bzrdir.has_branch():
330
if existing_bzrdir.has_workingtree():
331
raise errors.AlreadyBranchError(self.path)
333
raise errors.BranchExistsWithoutWorkingTree(self.path)
335
existing_bzrdir.create_branch()
336
existing_bzrdir.create_workingtree()
337
info_dialog(_('Initialize successful'),
338
_('Directory successfully initialized.'))
685
341
def on_menuitem_file_annotate_activate(self, widget):
686
342
""" File/Annotate... menu handler. """
687
343
if self.get_selected_right() is None:
688
error_dialog(_i18n('No file was selected'),
689
_i18n('Please select a file from the list.'))
344
error_dialog(_('No file was selected'),
345
_('Please select a file from the list.'))
692
348
branch = self.wt.branch
693
349
file_id = self.wt.path2id(self.wt.relpath(os.path.join(self.path, self.get_selected_right())))
695
window = GAnnotateWindow(all=False, plain=False, parent=self.window)
351
window = GAnnotateWindow(all=False, plain=False)
696
352
window.set_title(os.path.join(self.path, self.get_selected_right()) + " - Annotate")
697
353
config = GAnnotateConfig(window)
845
461
selected=self.get_selected_right(),
847
463
# get the menu items
848
m_open = menu.ui.get_widget('/context_right/open')
849
464
m_add = menu.ui.get_widget('/context_right/add')
850
465
m_remove = menu.ui.get_widget('/context_right/remove')
851
466
m_rename = menu.ui.get_widget('/context_right/rename')
852
m_revert = menu.ui.get_widget('/context_right/revert')
853
467
m_commit = menu.ui.get_widget('/context_right/commit')
854
m_annotate = menu.ui.get_widget('/context_right/annotate')
855
468
m_diff = menu.ui.get_widget('/context_right/diff')
856
469
# check if we're in a branch
858
471
from bzrlib.branch import Branch
859
472
Branch.open_containing(self.get_path())
861
m_open.set_sensitive(False)
862
m_add.set_sensitive(False)
863
m_remove.set_sensitive(False)
864
m_rename.set_sensitive(False)
865
m_revert.set_sensitive(False)
866
m_commit.set_sensitive(False)
867
m_annotate.set_sensitive(False)
868
m_diff.set_sensitive(False)
870
m_open.set_sensitive(True)
871
m_add.set_sensitive(True)
872
m_remove.set_sensitive(True)
873
m_rename.set_sensitive(True)
874
m_revert.set_sensitive(True)
875
m_commit.set_sensitive(True)
876
m_annotate.set_sensitive(True)
877
m_diff.set_sensitive(True)
878
except bzrerrors.NotBranchError:
879
m_open.set_sensitive(True)
473
m_add.set_sensitive(True)
474
m_remove.set_sensitive(True)
475
m_rename.set_sensitive(True)
476
m_commit.set_sensitive(True)
477
m_diff.set_sensitive(True)
478
except errors.NotBranchError:
880
479
m_add.set_sensitive(False)
881
480
m_remove.set_sensitive(False)
882
481
m_rename.set_sensitive(False)
883
m_revert.set_sensitive(False)
884
482
m_commit.set_sensitive(False)
885
m_annotate.set_sensitive(False)
886
483
m_diff.set_sensitive(False)
889
menu.right_context_menu().popup(None, None, None, 0,
892
menu.remote_context_menu().popup(None, None, None, 0,
485
menu.right_context_menu().popup(None, None, None, 0,
895
488
def on_treeview_right_row_activated(self, treeview, path, view_column):
896
489
""" Occurs when somebody double-clicks or enters an item in the
993
598
delta = self.wt.changes_from(tree2, want_unchanged=True)
995
600
# Add'em to the ListStore
998
statinfo = os.stat(self.path + os.sep + item)
1004
liststore.append([ gtk.STOCK_DIRECTORY,
1012
self._format_date(statinfo.st_mtime),
602
liststore.append([gtk.STOCK_DIRECTORY, item, ''])
1014
603
for item in files:
1015
604
status = 'unknown'
1017
605
if not self.notbranch:
1018
606
filename = self.wt.relpath(self.path + os.sep + item)
1023
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
1024
if rpathnew == filename:
1027
for rpath, id, kind in delta.added:
1028
if rpath == filename:
1031
for rpath, id, kind in delta.removed:
1032
if rpath == filename:
1035
for rpath, id, kind, text_modified, meta_modified in delta.modified:
1036
if rpath == filename:
1039
for rpath, id, kind in delta.unchanged:
1040
if rpath == filename:
1041
status = 'unchanged'
1043
for rpath, file_class, kind, id, entry in self.wt.list_files():
1044
if rpath == filename and file_class == 'I':
608
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
609
if rpathnew == filename:
611
for rpath, id, kind in delta.added:
612
if rpath == filename:
614
for rpath, id, kind in delta.removed:
615
if rpath == filename:
617
for rpath, id, kind, text_modified, meta_modified in delta.modified:
618
if rpath == filename:
620
for rpath, id, kind in delta.unchanged:
621
if rpath == filename:
623
for rpath, file_class, kind, id, entry in self.wt.list_files():
624
if rpath == filename and file_class == 'I':
628
# status = fileops.status(path + os.sep + item)
629
#except errors.PermissionDenied:
1049
632
if status == 'renamed':
1050
st = _i18n('renamed')
1051
634
elif status == 'removed':
1052
st = _i18n('removed')
1053
636
elif status == 'added':
1055
638
elif status == 'modified':
1056
st = _i18n('modified')
1057
640
elif status == 'unchanged':
1058
st = _i18n('unchanged')
1059
642
elif status == 'ignored':
1060
st = _i18n('ignored')
1062
st = _i18n('unknown')
1065
statinfo = os.stat(self.path + os.sep + item)
1071
liststore.append([gtk.STOCK_FILE,
1076
str(statinfo.st_size), # NOTE: if int used there it will fail for large files (size expressed as long int)
1077
self._format_size(statinfo.st_size),
1079
self._format_date(statinfo.st_mtime),
646
liststore.append([gtk.STOCK_FILE, item, st])
1082
648
# Create the columns and add them to the TreeView
1083
649
self.treeview_right.set_model(liststore)
1084
self._tvcolumn_filename = gtk.TreeViewColumn(_i18n('Filename'))
1085
self._tvcolumn_status = gtk.TreeViewColumn(_i18n('Status'))
1086
self._tvcolumn_size = gtk.TreeViewColumn(_i18n('Size'))
1087
self._tvcolumn_mtime = gtk.TreeViewColumn(_i18n('Last modified'))
1088
self.treeview_right.append_column(self._tvcolumn_filename)
1089
self.treeview_right.append_column(self._tvcolumn_status)
1090
self.treeview_right.append_column(self._tvcolumn_size)
1091
self.treeview_right.append_column(self._tvcolumn_mtime)
650
tvcolumn_filename = gtk.TreeViewColumn(_('Filename'))
651
tvcolumn_status = gtk.TreeViewColumn(_('Status'))
652
self.treeview_right.append_column(tvcolumn_filename)
653
self.treeview_right.append_column(tvcolumn_status)
1093
655
# Set up the cells
1094
656
cellpb = gtk.CellRendererPixbuf()
1095
657
cell = gtk.CellRendererText()
1096
self._tvcolumn_filename.pack_start(cellpb, False)
1097
self._tvcolumn_filename.pack_start(cell, True)
1098
self._tvcolumn_filename.set_attributes(cellpb, stock_id=0)
1099
self._tvcolumn_filename.add_attribute(cell, 'text', 2)
1100
self._tvcolumn_status.pack_start(cell, True)
1101
self._tvcolumn_status.add_attribute(cell, 'text', 3)
1102
self._tvcolumn_size.pack_start(cell, True)
1103
self._tvcolumn_size.add_attribute(cell, 'text', 6)
1104
self._tvcolumn_mtime.pack_start(cell, True)
1105
self._tvcolumn_mtime.add_attribute(cell, 'text', 8)
1107
# Set up the properties of the TreeView
1108
self.treeview_right.set_headers_visible(True)
1109
self.treeview_right.set_headers_clickable(True)
1110
self.treeview_right.set_search_column(1)
1111
self._tvcolumn_filename.set_resizable(True)
1112
self._tvcolumn_status.set_resizable(True)
1113
self._tvcolumn_size.set_resizable(True)
1114
self._tvcolumn_mtime.set_resizable(True)
1116
liststore.set_sort_func(13, self._sort_filelist_callback, None)
1117
liststore.set_sort_column_id(13, gtk.SORT_ASCENDING)
1118
self._tvcolumn_filename.set_sort_column_id(13)
1119
self._tvcolumn_status.set_sort_column_id(3)
1120
self._tvcolumn_size.set_sort_column_id(5)
1121
self._tvcolumn_mtime.set_sort_column_id(7)
658
tvcolumn_filename.pack_start(cellpb, False)
659
tvcolumn_filename.pack_start(cell, True)
660
tvcolumn_filename.set_attributes(cellpb, stock_id=0)
661
tvcolumn_filename.add_attribute(cell, 'text', 1)
662
tvcolumn_status.pack_start(cell, True)
663
tvcolumn_status.add_attribute(cell, 'text', 2)
1123
665
# Set sensitivity
1124
666
self.set_sensitivity()
1126
def get_selected_fileid(self):
1127
""" Get the file_id of the selected file. """
1128
treeselection = self.treeview_right.get_selection()
1129
(model, iter) = treeselection.get_selected()
1134
return model.get_value(iter, 9)
1136
668
def get_selected_right(self):
1137
669
""" Get the selected filename. """
1138
670
treeselection = self.treeview_right.get_selection()
1164
696
def set_sensitivity(self):
1165
697
""" Set menu and toolbar sensitivity. """
1168
self.menuitem_branch_init.set_sensitive(self.notbranch)
1169
self.menuitem_branch_get.set_sensitive(self.notbranch)
1170
self.menuitem_branch_checkout.set_sensitive(self.notbranch)
1171
self.menuitem_branch_pull.set_sensitive(not self.notbranch)
1172
self.menuitem_branch_push.set_sensitive(not self.notbranch)
1173
self.menuitem_branch_update.set_sensitive(not self.notbranch)
1174
self.menuitem_branch_revert.set_sensitive(not self.notbranch)
1175
self.menuitem_branch_merge.set_sensitive(not self.notbranch)
1176
self.menuitem_branch_commit.set_sensitive(not self.notbranch)
1177
self.menuitem_branch_tags.set_sensitive(not self.notbranch)
1178
self.menuitem_branch_status.set_sensitive(not self.notbranch)
1179
self.menuitem_branch_missing.set_sensitive(not self.notbranch)
1180
self.menuitem_branch_conflicts.set_sensitive(not self.notbranch)
1181
self.menuitem_stats.set_sensitive(not self.notbranch)
1182
self.menuitem_stats_diff.set_sensitive(not self.notbranch)
1183
self.menuitem_add_files.set_sensitive(not self.notbranch)
1184
self.menuitem_remove_files.set_sensitive(not self.notbranch)
1185
self.menuitem_file_make_directory.set_sensitive(not self.notbranch)
1186
self.menuitem_file_rename.set_sensitive(not self.notbranch)
1187
self.menuitem_file_move.set_sensitive(not self.notbranch)
1188
self.menuitem_file_annotate.set_sensitive(not self.notbranch)
1189
#self.menutoolbutton_diff.set_sensitive(True)
1190
self.toolbutton_diff.set_sensitive(not self.notbranch)
1191
self.toolbutton_log.set_sensitive(not self.notbranch)
1192
self.toolbutton_commit.set_sensitive(not self.notbranch)
1193
self.toolbutton_pull.set_sensitive(not self.notbranch)
1194
self.toolbutton_push.set_sensitive(not self.notbranch)
1195
self.toolbutton_update.set_sensitive(not self.notbranch)
1198
self.menuitem_branch_init.set_sensitive(False)
1199
self.menuitem_branch_get.set_sensitive(True)
1200
self.menuitem_branch_checkout.set_sensitive(True)
1201
self.menuitem_branch_pull.set_sensitive(False)
1202
self.menuitem_branch_push.set_sensitive(False)
1203
self.menuitem_branch_update.set_sensitive(False)
1204
self.menuitem_branch_revert.set_sensitive(False)
1205
self.menuitem_branch_merge.set_sensitive(False)
1206
self.menuitem_branch_commit.set_sensitive(False)
1207
self.menuitem_branch_tags.set_sensitive(True)
1208
self.menuitem_branch_status.set_sensitive(False)
1209
self.menuitem_branch_missing.set_sensitive(False)
1210
self.menuitem_branch_conflicts.set_sensitive(False)
1211
self.menuitem_stats.set_sensitive(True)
1212
self.menuitem_stats_diff.set_sensitive(False)
1213
self.menuitem_add_files.set_sensitive(False)
1214
self.menuitem_remove_files.set_sensitive(False)
1215
self.menuitem_file_make_directory.set_sensitive(False)
1216
self.menuitem_file_rename.set_sensitive(False)
1217
self.menuitem_file_move.set_sensitive(False)
1218
self.menuitem_file_annotate.set_sensitive(False)
1219
#self.menutoolbutton_diff.set_sensitive(True)
1220
self.toolbutton_diff.set_sensitive(False)
1221
self.toolbutton_log.set_sensitive(True)
1222
self.toolbutton_commit.set_sensitive(False)
1223
self.toolbutton_pull.set_sensitive(False)
1224
self.toolbutton_push.set_sensitive(False)
1225
self.toolbutton_update.set_sensitive(False)
698
self.menuitem_branch_init.set_sensitive(self.notbranch)
699
self.menuitem_branch_get.set_sensitive(self.notbranch)
700
self.menuitem_branch_checkout.set_sensitive(self.notbranch)
701
self.menuitem_branch_pull.set_sensitive(not self.notbranch)
702
self.menuitem_branch_push.set_sensitive(not self.notbranch)
703
self.menuitem_branch_merge.set_sensitive(not self.notbranch)
704
self.menuitem_branch_commit.set_sensitive(not self.notbranch)
705
self.menuitem_branch_status.set_sensitive(not self.notbranch)
706
self.menuitem_branch_missing.set_sensitive(not self.notbranch)
707
self.menuitem_stats.set_sensitive(not self.notbranch)
708
self.menuitem_add_files.set_sensitive(not self.notbranch)
709
self.menuitem_remove_files.set_sensitive(not self.notbranch)
710
self.menuitem_file_make_directory.set_sensitive(not self.notbranch)
711
self.menuitem_file_rename.set_sensitive(not self.notbranch)
712
self.menuitem_file_move.set_sensitive(not self.notbranch)
713
self.menuitem_file_annotate.set_sensitive(not self.notbranch)
714
#self.menutoolbutton_diff.set_sensitive(True)
715
self.toolbutton_diff.set_sensitive(not self.notbranch)
716
self.toolbutton_log.set_sensitive(not self.notbranch)
717
self.toolbutton_commit.set_sensitive(not self.notbranch)
718
self.toolbutton_pull.set_sensitive(not self.notbranch)
719
self.toolbutton_push.set_sensitive(not self.notbranch)
1227
721
def refresh_left(self):
1228
722
""" Refresh the bookmark list. """
1252
746
def refresh_right(self, path=None):
1253
747
""" Refresh the file list. """
1256
from bzrlib.workingtree import WorkingTree
1259
path = self.get_path()
1261
# A workaround for double-clicking Bookmarks
1262
if not os.path.exists(path):
1265
# Get ListStore and clear it
1266
liststore = self.treeview_right.get_model()
1269
# Show Status column
1270
self._tvcolumn_status.set_visible(True)
1275
# Fill the appropriate lists
1276
dotted_files = self.pref.get_preference('dotted_files', 'bool')
1277
ignored_files = self.pref.get_preference('ignored_files', 'bool')
1279
for item in os.listdir(path):
1280
if not dotted_files and item[0] == '.':
1282
if os.path.isdir(path + os.sep + item):
1287
# Try to open the working tree
1290
tree1 = WorkingTree.open_containing(path)[0]
1291
except (bzrerrors.NotBranchError, bzrerrors.NoWorkingTree):
748
from bzrlib.workingtree import WorkingTree
751
path = self.get_path()
753
# A workaround for double-clicking Bookmarks
754
if not os.path.exists(path):
757
# Get ListStore and clear it
758
liststore = self.treeview_right.get_model()
764
# Fill the appropriate lists
765
dotted_files = self.pref.get_preference('dotted_files', 'bool')
766
for item in os.listdir(path):
767
if not dotted_files and item[0] == '.':
769
if os.path.isdir(path + os.sep + item):
778
# add updir link to dirs
779
self._add_updir_to_dirlist(dirs, path)
781
# Try to open the working tree
784
tree1 = WorkingTree.open_containing(path)[0]
785
except (errors.NotBranchError, errors.NoWorkingTree):
789
branch = tree1.branch
790
tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
792
delta = tree1.changes_from(tree2, want_unchanged=True)
794
# Add'em to the ListStore
796
liststore.append([gtk.STOCK_DIRECTORY, item, ''])
1294
799
if not notbranch:
1295
branch = tree1.branch
1296
tree2 = tree1.branch.repository.revision_tree(branch.last_revision())
1298
delta = tree1.changes_from(tree2, want_unchanged=True)
1300
# Add'em to the ListStore
1303
statinfo = os.stat(self.path + os.sep + item)
1309
liststore.append([gtk.STOCK_DIRECTORY,
1317
self._format_date(statinfo.st_mtime),
1323
filename = tree1.relpath(path + os.sep + item)
1328
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
1329
if rpathnew == filename:
1332
for rpath, id, kind in delta.added:
1333
if rpath == filename:
1336
for rpath, id, kind in delta.removed:
1337
if rpath == filename:
1340
for rpath, id, kind, text_modified, meta_modified in delta.modified:
1341
if rpath == filename:
1344
for rpath, id, kind in delta.unchanged:
1345
if rpath == filename:
1346
status = 'unchanged'
1348
for rpath, file_class, kind, id, entry in self.wt.list_files():
1349
if rpath == filename and file_class == 'I':
1354
if status == 'renamed':
1355
st = _i18n('renamed')
1356
elif status == 'removed':
1357
st = _i18n('removed')
1358
elif status == 'added':
1360
elif status == 'modified':
1361
st = _i18n('modified')
1362
elif status == 'unchanged':
1363
st = _i18n('unchanged')
1364
elif status == 'ignored':
1365
st = _i18n('ignored')
1366
if not ignored_files:
1369
st = _i18n('unknown')
1372
statinfo = os.stat(self.path + os.sep + item)
1378
liststore.append([gtk.STOCK_FILE,
1383
str(statinfo.st_size),
1384
self._format_size(statinfo.st_size),
1386
self._format_date(statinfo.st_mtime),
1391
# Get ListStore and clear it
1392
liststore = self.treeview_right.get_model()
1395
# Hide Status column
1396
self._tvcolumn_status.set_visible(False)
1401
self._show_stock_image(gtk.STOCK_REFRESH)
1403
for (name, type) in self.remote_entries:
1404
if type.kind == 'directory':
1406
elif type.kind == 'file':
1410
""" Cache based on revision history. """
1411
def __init__(self, history):
1412
self._history = history
1414
def _lookup_revision(self, revid):
1415
for r in self._history:
1416
if r.revision_id == revid:
1418
rev = repo.get_revision(revid)
1419
self._history.append(rev)
1422
repo = self.remote_branch.repository
1424
revhistory = self.remote_branch.revision_history()
1426
revs = repo.get_revisions(revhistory)
1427
cache = HistoryCache(revs)
1428
except bzrerrors.InvalidHttpResponse:
1429
# Fallback to dummy algorithm, because of LP: #115209
1430
cache = HistoryCache([])
1433
if item.parent_id == self.remote_parent:
1434
rev = cache._lookup_revision(item.revision)
1435
liststore.append([ gtk.STOCK_DIRECTORY,
1443
self._format_date(rev.timestamp),
1446
while gtk.events_pending():
1447
gtk.main_iteration()
1450
if item.parent_id == self.remote_parent:
1451
rev = cache._lookup_revision(item.revision)
1452
liststore.append([ gtk.STOCK_FILE,
1457
str(item.text_size),
1458
self._format_size(item.text_size),
1460
self._format_date(rev.timestamp),
1463
while gtk.events_pending():
1464
gtk.main_iteration()
1466
self.image_location_error.destroy()
1468
# Columns should auto-size
1469
self.treeview_right.columns_autosize()
800
filename = tree1.relpath(path + os.sep + item)
802
for rpath, rpathnew, id, kind, text_modified, meta_modified in delta.renamed:
803
if rpathnew == filename:
805
for rpath, id, kind in delta.added:
806
if rpath == filename:
808
for rpath, id, kind in delta.removed:
809
if rpath == filename:
811
for rpath, id, kind, text_modified, meta_modified in delta.modified:
812
if rpath == filename:
814
for rpath, id, kind in delta.unchanged:
815
if rpath == filename:
817
for rpath, file_class, kind, id, entry in self.wt.list_files():
818
if rpath == filename and file_class == 'I':
822
# status = fileops.status(path + os.sep + item)
823
#except errors.PermissionDenied:
826
if status == 'renamed':
828
elif status == 'removed':
830
elif status == 'added':
832
elif status == 'modified':
834
elif status == 'unchanged':
836
elif status == 'ignored':
840
liststore.append([gtk.STOCK_FILE, item, st])
842
# Add the ListStore to the TreeView
843
self.treeview_right.set_model(liststore)
1471
845
# Set sensitivity
1472
846
self.set_sensitivity()
1521
def _sort_filelist_callback(self, model, iter1, iter2, data):
1522
""" The sort callback for the file list, return values:
1527
name1 = model.get_value(iter1, 2)
1528
name2 = model.get_value(iter2, 2)
1530
if model.get_value(iter1, 1):
1531
# item1 is a directory
1532
if not model.get_value(iter2, 1):
1536
# both of them are directories, we compare their names
1539
elif name1 == name2:
1544
# item1 is not a directory
1545
if model.get_value(iter2, 1):
1549
# both of them are files, compare them
1552
elif name1 == name2:
1557
def _format_size(self, size):
1558
""" Format size to a human readable format. """
1560
return "%d[B]" % (size,)
1561
size = size / 1000.0
1563
for metric in ["kB","MB","GB","TB"]:
1566
size = size / 1000.0
1567
return "%.1f[%s]" % (size,metric)
1569
def _format_date(self, timestamp):
1570
""" Format the time (given in secs) to a human readable format. """
1571
return time.ctime(timestamp)
1573
def _is_remote_dir(self, location):
1574
""" Determine whether the given location is a directory or not. """
1576
# We're in local mode
1579
branch, path = Branch.open_containing(location)
1580
for (name, type) in self.remote_entries:
1581
if name == path and type.kind == 'directory':
1584
# Either it's not a directory or not in the inventory
1587
def _show_stock_image(self, stock_id):
1588
""" Show a stock image next to the location entry. """
1589
self.image_location_error.destroy()
1590
self.image_location_error = gtk.image_new_from_stock(stock_id, gtk.ICON_SIZE_BUTTON)
1591
self.hbox_location.pack_start(self.image_location_error, False, False, 0)
1592
if sys.platform == 'win32':
1593
self.hbox_location.reorder_child(self.image_location_error, 2)
1595
self.hbox_location.reorder_child(self.image_location_error, 1)
1596
self.image_location_error.show()
1597
while gtk.events_pending():
1598
gtk.main_iteration()
1600
895
import ConfigParser
897
class OlivePreferences:
1603
898
""" A class which handles Olive's preferences. """
1604
def __init__(self, path=None):
1605
900
""" Initialize the Preferences class. """
1606
901
# Some default options
1607
902
self.defaults = { 'strict_commit' : False,
1608
903
'dotted_files' : False,
1609
'ignored_files' : True,
1610
904
'window_width' : 700,
1611
905
'window_height' : 400,
1612
906
'window_x' : 40,