14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
19
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, dialog):
25
from errors import show_bzr_error
27
from bzrlib.config import LocationConfig
28
import bzrlib.errors as errors
30
from dialog import error_dialog, info_dialog, question_dialog
32
from history import UrlHistory
34
class PushDialog(gtk.Dialog):
35
""" New implementation of the Push dialog. """
36
def __init__(self, branch, parent=None):
38
37
""" Initialize the Push dialog. """
39
self.gladefile = gladefile
40
self.glade = gtk.glade.XML(self.gladefile, 'window_push')
42
# Communication object
47
self.window = self.glade.get_widget('window_push')
49
# Dictionary for signal_autoconnect
50
dic = { "on_button_push_push_clicked": self.push,
51
"on_button_push_cancel_clicked": self.close,
52
"on_button_push_test_clicked": self.test,
53
"on_radiobutton_push_stored_toggled": self.stored_toggled,
54
"on_radiobutton_push_specific_toggled": self.specific_toggled, }
56
# Connect the signals to the handlers
57
self.glade.signal_autoconnect(dic)
59
# Get some useful widgets
60
self.radio_stored = self.glade.get_widget('radiobutton_push_stored')
61
self.radio_specific = self.glade.get_widget('radiobutton_push_specific')
62
self.entry_stored = self.glade.get_widget('entry_push_stored')
63
self.entry_location = self.glade.get_widget('entry_push_location')
64
self.check_remember = self.glade.get_widget('checkbutton_push_remember')
65
self.check_overwrite = self.glade.get_widget('checkbutton_push_overwrite')
66
self.check_create = self.glade.get_widget('checkbutton_push_create')
67
self.label_test = self.glade.get_widget('label_push_test')
68
self.image_test = self.glade.get_widget('image_push_test')
71
self.entry_location.set_sensitive(0)
72
self.check_remember.set_sensitive(0)
73
self.check_create.set_sensitive(0)
76
self.notbranch = False
78
loc = info.get_push_location(self.comm.get_path())
79
except errors.NotBranchError:
84
self.entry_stored.set_text(loc)
87
""" Display the Push dialog. """
89
self.dialog.error_dialog(_('Directory is not a branch'),
90
_('You can perform this action only in a branch.'))
94
self.width, self.height = self.window.get_size()
96
def stored_toggled(self, widget):
97
if widget.get_active():
98
self.entry_stored.set_sensitive(1)
99
self.entry_location.set_sensitive(0)
100
self.check_remember.set_sensitive(0)
101
self.check_create.set_sensitive(0)
103
self.entry_stored.set_sensitive(0)
104
self.entry_location.set_sensitive(1)
105
self.check_remember.set_sensitive(1)
106
self.check_create.set_sensitive(1)
108
def specific_toggled(self, widget):
109
if widget.get_active():
110
self.entry_stored.set_sensitive(0)
111
self.entry_location.set_sensitive(1)
112
self.check_remember.set_sensitive(1)
113
self.check_create.set_sensitive(1)
115
self.entry_stored.set_sensitive(1)
116
self.entry_location.set_sensitive(0)
117
self.check_remember.set_sensitive(0)
118
self.check_create.set_sensitive(0)
120
def push(self, widget):
122
self.comm.set_busy(self.window)
123
if self.radio_stored.get_active():
125
revs = commit.push(self.comm.get_path(),
126
overwrite=self.check_overwrite.get_active())
127
except errors.NotBranchError:
128
self.dialog.error_dialog(_('Directory is not a branch'),
129
_('You can perform this action only in a branch.'))
131
except errors.NoLocationKnown:
132
self.dialog.error_dialog(_('Push location is unknown'),
133
_('Please specify a location manually.'))
135
except errors.NonExistingParent, errmsg:
136
self.dialog.error_dialog(_('Non existing parent directory'),
137
_("The parent directory (%s)\ndoesn't exist.") % errmsg)
139
except errors.DivergedBranchesError:
140
self.dialog.error_dialog(_('Branches have been diverged'),
141
_('You cannot push if branches have diverged. Use the\noverwrite option if you want to push anyway.'))
145
elif self.radio_specific.get_active():
146
location = self.entry_location.get_text()
148
self.dialog.error_dialog(_('No location specified'),
149
_('Please specify a location or use the default.'))
153
revs = commit.push(self.comm.get_path(), location,
154
self.check_remember.get_active(),
155
self.check_overwrite.get_active(),
156
self.check_create.get_active())
157
except errors.NotBranchError:
158
self.dialog.error_dialog(_('Directory is not a branch'),
159
_('You can perform this action only in a branch.'))
160
self.comm.set_busy(self.window, False)
162
except errors.NonExistingParent, errmsg:
163
self.dialog.error_dialog(_('Non existing parent directory'),
164
_("The parent directory (%s)\ndoesn't exist.") % errmsg)
165
self.comm.set_busy(self.window, False)
167
except errors.DivergedBranchesError:
168
self.dialog.error_dialog(_('Branches have been diverged'),
169
_('You cannot push if branches have diverged. Use the\noverwrite option if you want to push anyway.'))
170
self.comm.set_busy(self.window, False)
172
except errors.PathPrefixNotCreated:
173
self.dialog.error_dialog(_('Path prefix not created'),
174
_("The path leading up to the specified location couldn't\nbe created."))
175
self.comm.set_busy(self.window, False)
180
# This should really never happen
184
self.dialog.info_dialog(_('Push successful'),
185
_('%d revision(s) pushed.') % revs)
187
def test(self, widget):
188
""" Test if write access possible. """
38
gtk.Dialog.__init__(self, title="Push - Olive",
41
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
47
self._label_location = gtk.Label(_("Location:"))
48
self._label_test = gtk.Label(_("(click the Test button to check write access)"))
49
self._check_remember = gtk.CheckButton(_("_Remember as default location"),
51
self._check_prefix = gtk.CheckButton(_("Create the path _leading up to the location"),
53
self._check_overwrite = gtk.CheckButton(_("_Overwrite target if diverged"),
55
self._combo = gtk.ComboBoxEntry()
56
self._button_test = gtk.Button(_("_Test"), use_underline=True)
57
self._button_push = gtk.Button(_("_Push"), use_underline=True)
58
self._hbox_location = gtk.HBox()
59
self._hbox_test = gtk.HBox()
60
self._image_test = gtk.Image()
63
self._button_test.connect('clicked', self._on_test_clicked)
64
self._button_push.connect('clicked', self._on_push_clicked)
67
self._image_test.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_BUTTON)
68
self._label_location.set_alignment(0, 0.5)
69
self._label_test.set_alignment(0, 0.5)
70
self._hbox_location.set_spacing(3)
71
self._hbox_test.set_spacing(3)
72
self.vbox.set_spacing(3)
75
self._hbox_location.pack_start(self._label_location, False, False)
76
self._hbox_location.pack_start(self._combo, True, True)
77
self._hbox_test.pack_start(self._image_test, False, False)
78
self._hbox_test.pack_start(self._label_test, True, True)
79
self.vbox.pack_start(self._hbox_location)
80
self.vbox.pack_start(self._check_remember)
81
self.vbox.pack_start(self._check_prefix)
82
self.vbox.pack_start(self._check_overwrite)
83
self.vbox.pack_start(self._hbox_test)
84
self.action_area.pack_start(self._button_test)
85
self.action_area.pack_end(self._button_push)
90
# Build location history
91
self._history = UrlHistory(self.branch.get_config(), 'push_history')
94
def _build_history(self):
95
""" Build up the location history. """
96
self._combo_model = gtk.ListStore(str)
97
for item in self._history.get_entries():
98
self._combo_model.append([ item ])
99
self._combo.set_model(self._combo_model)
100
self._combo.set_text_column(0)
102
location = self.branch.get_push_location()
104
self._combo.get_child().set_text(location)
106
def _on_test_clicked(self, widget):
107
""" Test button clicked handler. """
190
109
_urlRE = re.compile(r'^(?P<proto>[^:/\\]+)://(?P<path>.*)$')
192
if self.radio_stored.get_active():
193
url = self.entry_stored.get_text()
194
elif self.radio_specific.get_active():
195
url = self.entry_location.get_text()
111
url = self._combo.get_child().get_text()
197
113
m = _urlRE.match(url)
199
115
proto = m.groupdict()['proto']
200
if (proto == 'sftp') or (proto == 'file') or (proto == 'ftp'):
201
# have write acces (most probably)
202
self.image_test.set_from_stock(gtk.STOCK_YES, 4)
203
self.label_test.set_markup(_('<b>Write access is probably available</b>'))
116
# FIXME: This should ask the transport or branch rather than
117
# guessing using regular expressions. JRV 20070714
118
if proto in ('sftp', 'file', 'ftp'):
119
# have write access (most probably)
120
self._image_test.set_from_stock(gtk.STOCK_YES, 4)
121
self._label_test.set_markup(_('<b>Write access is probably available</b>'))
205
123
# no write access
206
self.image_test.set_from_stock(gtk.STOCK_NO, 4)
207
self.label_test.set_markup(_('<b>No write access</b>'))
124
self._image_test.set_from_stock(gtk.STOCK_NO, 4)
125
self._label_test.set_markup(_('<b>No write access</b>'))
209
127
# couldn't determine
210
self.image_test.set_from_stock(gtk.STOCK_DIALOG_QUESTION, 4)
211
self.label_test.set_markup(_('<b>Could not determine</b>'))
213
def close(self, widget=None):
214
self.window.destroy()
128
self._image_test.set_from_stock(gtk.STOCK_DIALOG_QUESTION, 4)
129
self._label_test.set_markup(_('<b>Could not determine</b>'))
132
def _on_push_clicked(self, widget):
133
""" Push button clicked handler. """
134
location = self._combo.get_child().get_text()
137
revs = do_push(self.branch,
139
overwrite=self._check_overwrite.get_active(),
140
remember=self._check_remember.get_active(),
141
create_prefix=self._check_prefix.get_active())
142
except errors.DivergedBranches:
143
response = question_dialog(_('Branches have been diverged'),
144
_('You cannot push if branches have diverged.\nOverwrite?'))
145
if response == gtk.RESPONSE_OK:
146
revs = do_push(self.branch, overwrite=True)
149
self._history.add_entry(location)
150
info_dialog(_('Push successful'),
151
_("%d revision(s) pushed.") % revs)
153
self.response(gtk.RESPONSE_OK)
155
def do_push(branch, location=None, remember=False, overwrite=False,
156
create_prefix=False):
157
""" Update a mirror of a branch.
159
:param branch: the source branch
161
:param location: the location of the branch that you'd like to update
163
:param remember: if set, the location will be stored
165
:param overwrite: overwrite target location if it diverged
167
:param create_prefix: create the path leading up to the branch if it doesn't exist
169
:return: number of revisions pushed
171
from bzrlib.bzrdir import BzrDir
172
from bzrlib.transport import get_transport
176
stored_loc = br_from.get_push_location()
178
if stored_loc is None:
179
error_dialog(_('Push location is unknown'),
180
_('Please specify a location manually.'))
183
location = stored_loc
185
transport = get_transport(location)
186
location_url = transport.base
188
if br_from.get_push_location() is None or remember:
189
br_from.set_push_location(location_url)
194
dir_to = BzrDir.open(location_url)
195
br_to = dir_to.open_branch()
196
except errors.NotBranchError:
198
transport = transport.clone('..')
199
if not create_prefix:
201
relurl = transport.relpath(location_url)
202
transport.mkdir(relurl)
203
except errors.NoSuchFile:
204
error_dialog(_('Non existing parent directory'),
205
_("The parent directory (%s)\ndoesn't exist.") % location)
208
current = transport.base
209
needed = [(transport, transport.relpath(location_url))]
212
transport, relpath = needed[-1]
213
transport.mkdir(relpath)
215
except errors.NoSuchFile:
216
new_transport = transport.clone('..')
217
needed.append((new_transport,
218
new_transport.relpath(transport.base)))
219
if new_transport.base == transport.base:
220
error_dialog(_('Path prefix not created'),
221
_("The path leading up to the specified location couldn't\nbe created."))
223
dir_to = br_from.bzrdir.clone(location_url,
224
revision_id=br_from.last_revision())
225
br_to = dir_to.open_branch()
226
count = len(br_to.revision_history())
228
old_rh = br_to.revision_history()
230
tree_to = dir_to.open_workingtree()
231
except errors.NotLocalUrl:
232
# FIXME - what to do here? how should we warn the user?
233
#warning('This transport does not update the working '
234
# 'tree of: %s' % (br_to.base,))
235
count = br_to.pull(br_from, overwrite)
236
except errors.NoWorkingTree:
237
count = br_to.pull(br_from, overwrite)
239
count = tree_to.pull(br_from, overwrite)