1
1
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
2
# Copyright (C) 2007 by Jelmer Vernooij <jelmer@samba.org>
3
4
# This program is free software; you can redistribute it and/or modify
4
5
# it under the terms of the GNU General Public License as published by
5
6
# the Free Software Foundation; either version 2 of the License, or
6
7
# (at your option) any later version.
8
9
# This program is distributed in the hope that it will be useful,
9
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
12
# GNU General Public License for more details.
13
14
# You should have received a copy of the GNU General Public License
14
15
# along with this program; if not, write to the Free Software
15
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
20
pygtk.require("2.0")
31
import olive.backend.commit as commit
32
import olive.backend.errors as errors
33
import olive.backend.info as info
36
""" Display Push dialog and perform the needed actions. """
37
def __init__(self, gladefile, comm):
26
from errors import show_bzr_error
28
# FIXME: This needs to be public JRV 20070714
29
from bzrlib.builtins import _create_prefix
30
from bzrlib.config import LocationConfig
31
import bzrlib.errors as errors
33
from dialog import error_dialog, info_dialog, question_dialog
35
from history import UrlHistory
37
class PushDialog(gtk.Dialog):
38
""" New implementation of the Push dialog. """
39
def __init__(self, repository, revid, branch=None, parent=None):
38
40
""" Initialize the Push dialog. """
39
self.gladefile = gladefile
40
self.glade = gtk.glade.XML(self.gladefile, 'window_push')
44
self.window = self.glade.get_widget('window_push')
46
# Dictionary for signal_autoconnect
47
dic = { "on_button_push_push_clicked": self.push,
48
"on_button_push_cancel_clicked": self.close,
49
"on_radiobutton_push_stored_toggled": self.stored_toggled,
50
"on_radiobutton_push_specific_toggled": self.specific_toggled, }
52
# Connect the signals to the handlers
53
self.glade.signal_autoconnect(dic)
55
# Get some useful widgets
56
self.entry_stored = self.glade.get_widget('entry_push_stored')
57
self.entry_location = self.glade.get_widget('entry_push_location')
58
self.check_remember = self.glade.get_widget('checkbutton_push_remember')
59
self.check_overwrite = self.glade.get_widget('checkbutton_push_overwrite')
60
self.check_create = self.glade.get_widget('checkbutton_push_create')
63
loc = info.get_push_location(self.comm.get_path())
65
self.entry_stored.set_text(loc)
68
""" Display the Push dialog. """
70
self.width, self.height = self.window.get_size()
72
def stored_toggled(self, widget):
73
if widget.get_active():
74
self.entry_stored.show()
75
self.entry_location.hide()
76
self.check_remember.hide()
77
self.check_create.hide()
78
self.window.resize(self.width, self.height)
80
self.entry_stored.hide()
81
self.entry_location.show()
82
self.check_remember.show()
83
self.check_create.show()
85
def specific_toggled(self, widget):
86
if widget.get_active():
87
self.entry_stored.hide()
88
self.entry_location.show()
89
self.check_remember.show()
90
self.check_create.show()
92
self.entry_stored.show()
93
self.entry_location.hide()
94
self.check_remember.hide()
95
self.check_create.hide()
97
def push(self, widget):
98
from dialog import OliveDialog
99
dialog = OliveDialog(self.gladefile)
101
radio_stored = self.glade.get_widget('radiobutton_push_stored')
102
radio_specific = self.glade.get_widget('radiobutton_push_specific')
41
gtk.Dialog.__init__(self, title="Push - Olive",
44
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
47
self.repository = repository
52
self._label_location = gtk.Label(_("Location:"))
53
self._combo = gtk.ComboBoxEntry()
54
self._button_push = gtk.Button(_("_Push"), use_underline=True)
55
self._hbox_location = gtk.HBox()
58
self._button_push.connect('clicked', self._on_push_clicked)
61
self._label_location.set_alignment(0, 0.5)
62
self._hbox_location.set_spacing(3)
63
self.vbox.set_spacing(3)
66
self._hbox_location.pack_start(self._label_location, False, False)
67
self._hbox_location.pack_start(self._combo, True, True)
68
self.vbox.pack_start(self._hbox_location)
69
self.action_area.pack_end(self._button_push)
74
# Build location history
75
self._history = UrlHistory(self.branch.get_config(), 'push_history')
78
def _build_history(self):
79
""" Build up the location history. """
80
self._combo_model = gtk.ListStore(str)
81
for item in self._history.get_entries():
82
self._combo_model.append([ item ])
83
self._combo.set_model(self._combo_model)
84
self._combo.set_text_column(0)
86
if self.branch is not None:
87
location = self.branch.get_push_location()
88
if location is not None:
89
self._combo.get_child().set_text(location)
92
def _on_push_clicked(self, widget):
93
""" Push button clicked handler. """
94
location = self._combo.get_child().get_text()
105
self.comm.set_busy(self.window)
106
if radio_stored.get_active():
108
revs = commit.push(self.comm.get_path(),
109
overwrite=self.check_overwrite.get_active())
110
except errors.NotBranchError:
111
dialog.error_dialog('Directory is not a branch.')
113
except errors.NoLocationKnown:
114
dialog.error_dialog('No location known.')
116
except errors.NonExistingParent, errmsg:
117
dialog.error_dialog('Parent directory doesn\'t exist: %s', errmsg)
119
except errors.DivergedBranchesError:
120
dialog.error_dialog('Branches have been diverged.')
124
elif radio_specific.get_active():
125
location = self.entry_location.get_text()
127
dialog.error_dialog('No location specified.')
131
revs = commit.push(self.comm.get_path(), location,
132
self.check_remember.get_active(),
133
self.check_overwrite.get_active(),
134
self.check_create.get_active())
135
except errors.NotBranchError:
136
dialog.error_dialog('Directory is not a branch.')
137
self.comm.set_busy(self.window, False)
139
except errors.NonExistingParent, errmsg:
140
dialog.error_dialog('Parent directory doesn\'t exist: %s', errmsg)
141
self.comm.set_busy(self.window, False)
143
except errors.DivergedBranchesError:
144
dialog.error_dialog('Branches have been diverged.')
145
self.comm.set_busy(self.window, False)
147
except errors.PathPrefixNotCreated:
148
dialog.error_dialog('Path prefix couldn\'t be created.')
149
self.comm.set_busy(self.window, False)
96
if self.branch is not None and self.branch.get_push_location() is None:
97
response = question_dialog(_('Set default push location'),
98
_('There is no default push location set.\nSet %r as default now?') % location)
99
if response == gtk.RESPONSE_OK:
100
self.branch.set_push_location(location)
103
revs = do_push(self.branch, location=location, overwrite=False)
104
except errors.DivergedBranches:
105
response = question_dialog(_('Branches have been diverged'),
106
_('You cannot push if branches have diverged.\nOverwrite?'))
107
if response == gtk.RESPONSE_YES:
108
revs = do_push(self.branch, location=location, overwrite=True)
110
self._history.add_entry(location)
111
info_dialog(_('Push successful'),
112
_("%d revision(s) pushed.") % revs)
114
self.response(gtk.RESPONSE_OK)
116
def do_push(br_from, location, overwrite):
117
""" Update a mirror of a branch.
119
:param br_from: the source branch
121
:param location: the location of the branch that you'd like to update
123
:param overwrite: overwrite target location if it diverged
125
:return: number of revisions pushed
127
from bzrlib.bzrdir import BzrDir
128
from bzrlib.transport import get_transport
130
transport = get_transport(location)
131
location_url = transport.base
136
dir_to = BzrDir.open(location_url)
137
br_to = dir_to.open_branch()
138
except errors.NotBranchError:
140
transport = transport.clone('..')
142
relurl = transport.relpath(location_url)
143
transport.mkdir(relurl)
144
except errors.NoSuchFile:
145
response = question_dialog(_('Non existing parent directory'),
146
_("The parent directory (%s)\ndoesn't exist. Create?") % location)
147
if response == gtk.RESPONSE_OK:
148
_create_prefix(transport)
151
dir_to = br_from.bzrdir.clone(location_url,
152
revision_id=br_from.last_revision())
153
br_to = dir_to.open_branch()
154
count = len(br_to.revision_history())
156
old_rh = br_to.revision_history()
158
tree_to = dir_to.open_workingtree()
159
except errors.NotLocalUrl:
160
# FIXME - what to do here? how should we warn the user?
161
count = br_to.pull(br_from, overwrite)
162
except errors.NoWorkingTree:
163
count = br_to.pull(br_from, overwrite)
154
# This should really never happen
158
dialog.info_dialog('%d revision(s) pushed.' % revs)
160
def close(self, widget=None):
161
self.window.destroy()
165
count = tree_to.pull(br_from, overwrite)