/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to push.py

  • Committer: Vincent Ladeuil
  • Date: 2008-06-10 15:25:47 UTC
  • mto: This revision was merged to the branch mainline in revision 504.
  • Revision ID: v.ladeuil+lp@free.fr-20080610152547-dwmil1p8pd0mfpnl
Fix third failing test (thanks to jam).

* tests/test_commit.py:
(TestPendingRevisions.test_pending_revisions_multi_merge): Fix
provided by jam: bzr we now filter the pending merges so that only
the 'heads()' are included. We just ensure that the pending merges
contain the unique tips for the ancestries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2006 by Szilveszter Farkas (Phanatic) <szilveszter.farkas@gmail.com>
 
2
# Copyright (C) 2007 by Jelmer Vernooij <jelmer@samba.org>
2
3
#
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
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
16
17
 
17
 
import sys
18
 
 
19
18
try:
20
19
    import pygtk
21
20
    pygtk.require("2.0")
22
21
except:
23
22
    pass
24
 
try:
25
 
    import gtk
26
 
    import gtk.gdk
27
 
    import gtk.glade
28
 
except:
29
 
    sys.exit(1)
30
 
 
31
 
import olive.backend.commit as commit
 
23
    
 
24
import gtk
 
25
 
 
26
from errors import show_bzr_error
 
27
 
 
28
# FIXME: This needs to be public JRV 20070714
 
29
from bzrlib.builtins import _create_prefix
 
30
from bzrlib.config import LocationConfig
32
31
import bzrlib.errors as errors
33
 
import olive.backend.info as info
34
 
 
35
 
class OlivePush:
36
 
    """ Display Push dialog and perform the needed actions. """
37
 
    def __init__(self, gladefile, comm, dialog):
 
32
 
 
33
from bzrlib.plugins.gtk import _i18n
 
34
from dialog import error_dialog, info_dialog, question_dialog
 
35
 
 
36
from history import UrlHistory
 
37
 
 
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')
41
 
        
42
 
        # Communication object
43
 
        self.comm = comm
44
 
        # Dialog object
45
 
        self.dialog = dialog
46
 
        
47
 
        self.window = self.glade.get_widget('window_push')
48
 
        
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, }
55
 
        
56
 
        # Connect the signals to the handlers
57
 
        self.glade.signal_autoconnect(dic)
58
 
        
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')
69
 
        
70
 
        # Get stored location
71
 
        self.notbranch = False
72
 
        try:
73
 
            loc = info.get_push_location(self.comm.get_path())
74
 
        except errors.NotBranchError:
75
 
            self.notbranch = True
76
 
            return
77
 
 
78
 
        if loc is not None:
79
 
            self.entry_stored.set_text(loc)
80
 
    
81
 
    def display(self):
82
 
        """ Display the Push dialog. """
83
 
        if self.notbranch:
84
 
            self.dialog.error_dialog(_('Directory is not a branch'),
85
 
                                     _('You can perform this action only in a branch.'))
86
 
            self.close()
87
 
        else:
88
 
            self.window.show()
89
 
            self.width, self.height = self.window.get_size()
90
 
    
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)
98
 
        else:
99
 
            self.entry_stored.hide()
100
 
            self.entry_location.show()
101
 
            self.check_remember.show()
102
 
            self.check_create.show()
103
 
    
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()
110
 
        else:
111
 
            self.entry_stored.show()
112
 
            self.entry_location.hide()
113
 
            self.check_remember.hide()
114
 
            self.check_create.hide()
115
 
    
116
 
    def push(self, widget):
 
42
        gtk.Dialog.__init__(self, title="Push - Olive",
 
43
                                  parent=parent,
 
44
                                  flags=0,
 
45
                                  buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
 
46
        
 
47
        # Get arguments
 
48
        self.repository = repository
 
49
        self.revid = revid
 
50
        self.branch = branch
 
51
        
 
52
        # Create the widgets
 
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()
 
57
        
 
58
        # Set callbacks
 
59
        self._button_push.connect('clicked', self._on_push_clicked)
 
60
        
 
61
        # Set properties
 
62
        self._label_location.set_alignment(0, 0.5)
 
63
        self._hbox_location.set_spacing(3)
 
64
        self.vbox.set_spacing(3)
 
65
        
 
66
        # Pack widgets
 
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)
 
71
        
 
72
        # Show the dialog
 
73
        self.vbox.show_all()
 
74
        
 
75
        # Build location history
 
76
        self._history = UrlHistory(self.branch.get_config(), 'push_history')
 
77
        self._build_history()
 
78
        
 
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)
 
86
        
 
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)
 
91
    
 
92
    @show_bzr_error
 
93
    def _on_push_clicked(self, widget):
 
94
        """ Push button clicked handler. """
 
95
        location = self._combo.get_child().get_text()
117
96
        revs = 0
118
 
        self.comm.set_busy(self.window)
119
 
        if self.radio_stored.get_active():
120
 
            try:
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.'))
126
 
                return
127
 
            except errors.NoLocationKnown:
128
 
                self.dialog.error_dialog(_('Push location is unknown'),
129
 
                                         _('Please specify a location manually.'))
130
 
                return
131
 
            except errors.NonExistingParent, errmsg:
132
 
                self.dialog.error_dialog(_('Non existing parent directory'),
133
 
                                         _("The parent directory (%s)\ndoesn't exist.") % errmsg)
134
 
                return
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.'))
138
 
                return
139
 
            except:
140
 
                raise
141
 
        elif self.radio_specific.get_active():
142
 
            location = self.entry_location.get_text()
143
 
            if location == '':
144
 
                self.dialog.error_dialog(_('No location specified'),
145
 
                                         _('Please specify a location or use the default.'))
146
 
                return
147
 
            
148
 
            try:
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)
157
 
                return
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)
162
 
                return
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)
167
 
                return
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)
172
 
                return
173
 
            except:
174
 
                raise
175
 
        else:
176
 
            # This should really never happen
177
 
            pass
178
 
        
179
 
        self.close()
180
 
        self.dialog.info_dialog(_('Push successful'),
181
 
                                _('%d revision(s) pushed.') % revs)
182
 
    
183
 
    def test(self, widget):
184
 
        """ Test if write access possible. """
185
 
        import re
186
 
        _urlRE = re.compile(r'^(?P<proto>[^:/\\]+)://(?P<path>.*)$')
187
 
        
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()
192
 
        
193
 
        m = _urlRE.match(url)
194
 
        if m:
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)
 
102
 
 
103
        try:
 
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)
 
110
        
 
111
        self._history.add_entry(location)
 
112
        info_dialog(_i18n('Push successful'),
 
113
                    _i18n("%d revision(s) pushed.") % revs)
 
114
        
 
115
        self.response(gtk.RESPONSE_OK)
 
116
 
 
117
def do_push(br_from, location, overwrite):
 
118
    """ Update a mirror of a branch.
 
119
    
 
120
    :param br_from: the source branch
 
121
    
 
122
    :param location: the location of the branch that you'd like to update
 
123
    
 
124
    :param overwrite: overwrite target location if it diverged
 
125
    
 
126
    :return: number of revisions pushed
 
127
    """
 
128
    from bzrlib.bzrdir import BzrDir
 
129
    from bzrlib.transport import get_transport
 
130
        
 
131
    transport = get_transport(location)
 
132
    location_url = transport.base
 
133
 
 
134
    old_rh = []
 
135
 
 
136
    try:
 
137
        dir_to = BzrDir.open(location_url)
 
138
        br_to = dir_to.open_branch()
 
139
    except errors.NotBranchError:
 
140
        # create a branch.
 
141
        transport = transport.clone('..')
 
142
        try:
 
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)
200
150
            else:
201
 
                # no write access
202
 
                self.image_test.set_from_stock(gtk.STOCK_NO, 4)
203
 
                self.label_test.set_markup(_('<b>No write access</b>'))
 
151
                return
 
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())
 
156
    else:
 
157
        old_rh = br_to.revision_history()
 
158
        try:
 
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)
204
165
        else:
205
 
            # couldn't determine
206
 
            self.image_test.set_from_stock(gtk.STOCK_DIALOG_QUESTION, 4)
207
 
            self.label_test.set_markup(_('<b>Could not determine</b>'))
208
 
    
209
 
    def close(self, widget=None):
210
 
        self.window.destroy()
 
166
            count = tree_to.pull(br_from, overwrite)
 
167
 
 
168
    return count