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 olive import delimiter
26
from errors import show_bzr_error
28
from bzrlib.config import LocationConfig
29
import bzrlib.errors as errors
31
from olive.dialog import error_dialog, info_dialog, question_dialog
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_radiobutton_push_stored_toggled": self.stored_toggled,
53
"on_radiobutton_push_specific_toggled": self.specific_toggled, }
55
# Connect the signals to the handlers
56
self.glade.signal_autoconnect(dic)
58
# Get some useful widgets
59
self.entry_stored = self.glade.get_widget('entry_push_stored')
60
self.entry_location = self.glade.get_widget('entry_push_location')
61
self.check_remember = self.glade.get_widget('checkbutton_push_remember')
62
self.check_overwrite = self.glade.get_widget('checkbutton_push_overwrite')
63
self.check_create = self.glade.get_widget('checkbutton_push_create')
66
self.notbranch = False
68
loc = info.get_push_location(self.comm.get_path())
69
except errors.NotBranchError:
74
self.entry_stored.set_text(loc)
77
""" Display the Push dialog. """
79
self.dialog.error_dialog(_('Directory is not a branch'),
80
_('You can perform this action only in a branch.'))
84
self.width, self.height = self.window.get_size()
86
def stored_toggled(self, widget):
87
if widget.get_active():
88
self.entry_stored.show()
89
self.entry_location.hide()
90
self.check_remember.hide()
91
self.check_create.hide()
92
self.window.resize(self.width, self.height)
94
self.entry_stored.hide()
95
self.entry_location.show()
96
self.check_remember.show()
97
self.check_create.show()
99
def specific_toggled(self, widget):
100
if widget.get_active():
101
self.entry_stored.hide()
102
self.entry_location.show()
103
self.check_remember.show()
104
self.check_create.show()
106
self.entry_stored.show()
107
self.entry_location.hide()
108
self.check_remember.hide()
109
self.check_create.hide()
111
def push(self, widget):
112
radio_stored = self.glade.get_widget('radiobutton_push_stored')
113
radio_specific = self.glade.get_widget('radiobutton_push_specific')
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
93
def _build_history(self):
94
""" Build up the location history. """
95
config = LocationConfig(self.branch.base)
96
history = config.get_user_option('gpush_history')
97
if history is not None:
98
self._combo_model = gtk.ListStore(str)
99
for item in history.split(delimiter):
100
self._combo_model.append([ item ])
101
self._combo.set_model(self._combo_model)
102
self._combo.set_text_column(0)
104
location = self.branch.get_push_location()
106
self._combo.get_child().set_text(location)
108
def _add_to_history(self, location):
109
""" Add specified location to the history (if not yet added). """
110
config = LocationConfig(self.branch.base)
111
history = config.get_user_option('gpush_history')
113
config.set_user_option('gpush_history', location)
115
h = history.split(delimiter)
116
if location not in h:
118
config.set_user_option('gpush_history', delimiter.join(h))
120
def _on_test_clicked(self, widget):
121
""" Test button clicked handler. """
123
_urlRE = re.compile(r'^(?P<proto>[^:/\\]+)://(?P<path>.*)$')
125
url = self._combo.get_child().get_text()
127
m = _urlRE.match(url)
129
proto = m.groupdict()['proto']
130
if (proto == 'sftp') or (proto == 'file') or (proto == 'ftp'):
131
# have write acces (most probably)
132
self._image_test.set_from_stock(gtk.STOCK_YES, 4)
133
self._label_test.set_markup(_('<b>Write access is probably available</b>'))
136
self._image_test.set_from_stock(gtk.STOCK_NO, 4)
137
self._label_test.set_markup(_('<b>No write access</b>'))
140
self._image_test.set_from_stock(gtk.STOCK_DIALOG_QUESTION, 4)
141
self._label_test.set_markup(_('<b>Could not determine</b>'))
144
def _on_push_clicked(self, widget):
145
""" Push button clicked handler. """
146
location = self._combo.get_child().get_text()
116
self.comm.set_busy(self.window)
117
if radio_stored.get_active():
119
revs = commit.push(self.comm.get_path(),
120
overwrite=self.check_overwrite.get_active())
121
except errors.NotBranchError:
122
self.dialog.error_dialog(_('Directory is not a branch'),
123
_('You can perform this action only in a branch.'))
125
except errors.NoLocationKnown:
126
self.dialog.error_dialog(_('Push location is unknown'),
127
_('Please specify a location manually.'))
129
except errors.NonExistingParent, errmsg:
130
self.dialog.error_dialog(_('Non existing parent directory'),
131
_("The parent directory (%s)\ndoesn't exist.") % errmsg)
133
except errors.DivergedBranchesError:
134
self.dialog.error_dialog(_('Branches have been diverged'),
135
_('You cannot push if branches have diverged. Use the\noverwrite option if you want to push anyway.'))
139
elif radio_specific.get_active():
140
location = self.entry_location.get_text()
142
self.dialog.error_dialog(_('No location specified'),
143
_('Please specify a location or use the default.'))
147
revs = commit.push(self.comm.get_path(), location,
148
self.check_remember.get_active(),
149
self.check_overwrite.get_active(),
150
self.check_create.get_active())
151
except errors.NotBranchError:
152
self.dialog.error_dialog(_('Directory is not a branch'),
153
_('You can perform this action only in a branch.'))
154
self.comm.set_busy(self.window, False)
156
except errors.NonExistingParent, errmsg:
157
self.dialog.error_dialog(_('Non existing parent directory'),
158
_("The parent directory (%s)\ndoesn't exist.") % errmsg)
159
self.comm.set_busy(self.window, False)
161
except errors.DivergedBranchesError:
162
self.dialog.error_dialog(_('Branches have been diverged'),
163
_('You cannot push if branches have diverged. Use the\noverwrite option if you want to push anyway.'))
164
self.comm.set_busy(self.window, False)
166
except errors.PathPrefixNotCreated:
167
self.dialog.error_dialog(_('Path prefix not created'),
168
_("The path leading up to the specified location couldn't\nbe created."))
169
self.comm.set_busy(self.window, False)
174
# This should really never happen
178
self.dialog.info_dialog(_('Push successful'),
179
_('%d revision(s) pushed.') % revs)
181
def close(self, widget=None):
182
self.window.destroy()
149
revs = do_push(self.branch,
151
overwrite=self._check_overwrite.get_active(),
152
remember=self._check_remember.get_active(),
153
create_prefix=self._check_prefix.get_active())
154
except errors.DivergedBranches:
155
response = question_dialog(_('Branches have been diverged'),
156
_('You cannot push if branches have diverged.\nOverwrite?'))
157
if response == gtk.RESPONSE_OK:
158
revs = do_push(self.branch, overwrite=True)
161
self._add_to_history(location)
162
info_dialog(_('Push successful'),
163
_("%d revision(s) pushed.") % revs)
165
self.response(gtk.RESPONSE_OK)
167
def do_push(branch, location=None, remember=False, overwrite=False,
168
create_prefix=False):
169
""" Update a mirror of a branch.
171
:param branch: the source branch
173
:param location: the location of the branch that you'd like to update
175
:param remember: if set, the location will be stored
177
:param overwrite: overwrite target location if it diverged
179
:param create_prefix: create the path leading up to the branch if it doesn't exist
181
:return: number of revisions pushed
183
from bzrlib.bzrdir import BzrDir
184
from bzrlib.transport import get_transport
188
stored_loc = br_from.get_push_location()
190
if stored_loc is None:
191
error_dialog(_('Push location is unknown'),
192
_('Please specify a location manually.'))
195
location = stored_loc
197
transport = get_transport(location)
198
location_url = transport.base
200
if br_from.get_push_location() is None or remember:
201
br_from.set_push_location(location_url)
206
dir_to = BzrDir.open(location_url)
207
br_to = dir_to.open_branch()
208
except errors.NotBranchError:
210
transport = transport.clone('..')
211
if not create_prefix:
213
relurl = transport.relpath(location_url)
214
transport.mkdir(relurl)
215
except errors.NoSuchFile:
216
error_dialog(_('Non existing parent directory'),
217
_("The parent directory (%s)\ndoesn't exist.") % location)
220
current = transport.base
221
needed = [(transport, transport.relpath(location_url))]
224
transport, relpath = needed[-1]
225
transport.mkdir(relpath)
227
except errors.NoSuchFile:
228
new_transport = transport.clone('..')
229
needed.append((new_transport,
230
new_transport.relpath(transport.base)))
231
if new_transport.base == transport.base:
232
error_dialog(_('Path prefix not created'),
233
_("The path leading up to the specified location couldn't\nbe created."))
235
dir_to = br_from.bzrdir.clone(location_url,
236
revision_id=br_from.last_revision())
237
br_to = dir_to.open_branch()
238
count = len(br_to.revision_history())
240
old_rh = br_to.revision_history()
242
tree_to = dir_to.open_workingtree()
243
except errors.NotLocalUrl:
244
# FIXME - what to do here? how should we warn the user?
245
#warning('This transport does not update the working '
246
# 'tree of: %s' % (br_to.base,))
247
count = br_to.pull(br_from, overwrite)
248
except errors.NoWorkingTree:
249
count = br_to.pull(br_from, overwrite)
251
count = tree_to.pull(br_from, overwrite)