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, dialog):
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 bzrlib.plugins.gtk import _i18n
34
from dialog import error_dialog, info_dialog, question_dialog
36
from history import UrlHistory
38
class PushDialog(gtk.Dialog):
39
""" New implementation of the Push dialog. """
40
def __init__(self, repository, revid, branch=None, parent=None):
38
41
""" 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.notbranch = False
73
loc = info.get_push_location(self.comm.get_path())
74
except errors.NotBranchError:
79
self.entry_stored.set_text(loc)
82
""" Display the Push dialog. """
84
self.dialog.error_dialog(_('Directory is not a branch'),
85
_('You can perform this action only in a branch.'))
89
self.width, self.height = self.window.get_size()
91
def stored_toggled(self, widget):
92
if widget.get_active():
93
self.entry_stored.show()
94
self.entry_location.hide()
95
self.check_remember.hide()
96
self.check_create.hide()
97
self.window.resize(self.width, self.height)
99
self.entry_stored.hide()
100
self.entry_location.show()
101
self.check_remember.show()
102
self.check_create.show()
104
def specific_toggled(self, widget):
105
if widget.get_active():
106
self.entry_stored.hide()
107
self.entry_location.show()
108
self.check_remember.show()
109
self.check_create.show()
111
self.entry_stored.show()
112
self.entry_location.hide()
113
self.check_remember.hide()
114
self.check_create.hide()
116
def push(self, widget):
42
gtk.Dialog.__init__(self, title="Push - Olive",
45
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
48
self.repository = repository
53
self._label_location = gtk.Label(_i18n("Location:"))
54
self._combo = gtk.ComboBoxEntry()
55
self._button_push = gtk.Button(_i18n("_Push"), use_underline=True)
56
self._hbox_location = gtk.HBox()
59
self._button_push.connect('clicked', self._on_push_clicked)
62
self._label_location.set_alignment(0, 0.5)
63
self._hbox_location.set_spacing(3)
64
self.vbox.set_spacing(3)
67
self._hbox_location.pack_start(self._label_location, False, False)
68
self._hbox_location.pack_start(self._combo, True, True)
69
self.vbox.pack_start(self._hbox_location)
70
self.action_area.pack_end(self._button_push)
75
# Build location history
76
self._history = UrlHistory(self.branch.get_config(), 'push_history')
79
def _build_history(self):
80
""" Build up the location history. """
81
self._combo_model = gtk.ListStore(str)
82
for item in self._history.get_entries():
83
self._combo_model.append([ item ])
84
self._combo.set_model(self._combo_model)
85
self._combo.set_text_column(0)
87
if self.branch is not None:
88
location = self.branch.get_push_location()
89
if location is not None:
90
self._combo.get_child().set_text(location)
93
def _on_push_clicked(self, widget):
94
""" Push button clicked handler. """
95
location = self._combo.get_child().get_text()
118
self.comm.set_busy(self.window)
119
if self.radio_stored.get_active():
121
revs = commit.push(self.comm.get_path(),
122
overwrite=self.check_overwrite.get_active())
123
except errors.NotBranchError:
124
self.dialog.error_dialog(_('Directory is not a branch'),
125
_('You can perform this action only in a branch.'))
127
except errors.NoLocationKnown:
128
self.dialog.error_dialog(_('Push location is unknown'),
129
_('Please specify a location manually.'))
131
except errors.NonExistingParent, errmsg:
132
self.dialog.error_dialog(_('Non existing parent directory'),
133
_("The parent directory (%s)\ndoesn't exist.") % errmsg)
135
except errors.DivergedBranchesError:
136
self.dialog.error_dialog(_('Branches have been diverged'),
137
_('You cannot push if branches have diverged. Use the\noverwrite option if you want to push anyway.'))
141
elif self.radio_specific.get_active():
142
location = self.entry_location.get_text()
144
self.dialog.error_dialog(_('No location specified'),
145
_('Please specify a location or use the default.'))
149
revs = commit.push(self.comm.get_path(), location,
150
self.check_remember.get_active(),
151
self.check_overwrite.get_active(),
152
self.check_create.get_active())
153
except errors.NotBranchError:
154
self.dialog.error_dialog(_('Directory is not a branch'),
155
_('You can perform this action only in a branch.'))
156
self.comm.set_busy(self.window, False)
158
except errors.NonExistingParent, errmsg:
159
self.dialog.error_dialog(_('Non existing parent directory'),
160
_("The parent directory (%s)\ndoesn't exist.") % errmsg)
161
self.comm.set_busy(self.window, False)
163
except errors.DivergedBranchesError:
164
self.dialog.error_dialog(_('Branches have been diverged'),
165
_('You cannot push if branches have diverged. Use the\noverwrite option if you want to push anyway.'))
166
self.comm.set_busy(self.window, False)
168
except errors.PathPrefixNotCreated:
169
self.dialog.error_dialog(_('Path prefix not created'),
170
_("The path leading up to the specified location couldn't\nbe created."))
171
self.comm.set_busy(self.window, False)
176
# This should really never happen
180
self.dialog.info_dialog(_('Push successful'),
181
_('%d revision(s) pushed.') % revs)
183
def test(self, widget):
184
""" Test if write access possible. """
186
_urlRE = re.compile(r'^(?P<proto>[^:/\\]+)://(?P<path>.*)$')
188
if self.radio_stored.get_active():
189
url = self.entry_stored.get_text()
190
elif self.radio_specific.get_active():
191
url = self.entry_location.get_text()
193
m = _urlRE.match(url)
195
proto = m.groupdict()['proto']
196
if (proto == 'sftp') or (proto == 'file') or (proto == 'ftp'):
197
# have write acces (most probably)
198
self.image_test.set_from_stock(gtk.STOCK_YES, 4)
199
self.label_test.set_markup(_('<b>Write access is available most probably</b>'))
97
if self.branch is not None and self.branch.get_push_location() is None:
98
response = question_dialog(_i18n('Set default push location'),
99
_i18n('There is no default push location set.\nSet %r as default now?') % location)
100
if response == gtk.RESPONSE_OK:
101
self.branch.set_push_location(location)
104
revs = do_push(self.branch, location=location, overwrite=False)
105
except errors.DivergedBranches:
106
response = question_dialog(_i18n('Branches have been diverged'),
107
_i18n('You cannot push if branches have diverged.\nOverwrite?'))
108
if response == gtk.RESPONSE_YES:
109
revs = do_push(self.branch, location=location, overwrite=True)
111
self._history.add_entry(location)
112
info_dialog(_i18n('Push successful'),
113
_i18n("%d revision(s) pushed.") % revs)
115
self.response(gtk.RESPONSE_OK)
117
def do_push(br_from, location, overwrite):
118
""" Update a mirror of a branch.
120
:param br_from: the source branch
122
:param location: the location of the branch that you'd like to update
124
:param overwrite: overwrite target location if it diverged
126
:return: number of revisions pushed
128
from bzrlib.bzrdir import BzrDir
129
from bzrlib.transport import get_transport
131
transport = get_transport(location)
132
location_url = transport.base
137
dir_to = BzrDir.open(location_url)
138
br_to = dir_to.open_branch()
139
except errors.NotBranchError:
141
transport = transport.clone('..')
143
relurl = transport.relpath(location_url)
144
transport.mkdir(relurl)
145
except errors.NoSuchFile:
146
response = question_dialog(_i18n('Non existing parent directory'),
147
_i18n("The parent directory (%s)\ndoesn't exist. Create?") % location)
148
if response == gtk.RESPONSE_OK:
149
_create_prefix(transport)
202
self.image_test.set_from_stock(gtk.STOCK_NO, 4)
203
self.label_test.set_markup(_('<b>No write access</b>'))
152
dir_to = br_from.bzrdir.clone(location_url,
153
revision_id=br_from.last_revision())
154
br_to = dir_to.open_branch()
155
count = len(br_to.revision_history())
157
old_rh = br_to.revision_history()
159
tree_to = dir_to.open_workingtree()
160
except errors.NotLocalUrl:
161
# FIXME - what to do here? how should we warn the user?
162
count = br_to.pull(br_from, overwrite)
163
except errors.NoWorkingTree:
164
count = br_to.pull(br_from, overwrite)
206
self.image_test.set_from_stock(gtk.STOCK_DIALOG_QUESTION, 4)
207
self.label_test.set_markup(_('<b>Could not determine</b>'))
209
def close(self, widget=None):
210
self.window.destroy()
166
count = tree_to.pull(br_from, overwrite)