/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: Mateusz Korniak
  • Date: 2007-07-21 13:16:33 UTC
  • mto: This revision was merged to the branch mainline in revision 248.
  • Revision ID: matkor@laptop-hp-20070721131633-t40kxs20j1q2fvvc
Context menu "Remove and delete added"
Acts like "Remove" but also deletes file locally.

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
21
22
    pass
22
23
    
23
24
import gtk
24
 
import gtk.gdk
25
 
import gtk.glade
26
 
 
 
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
27
31
import bzrlib.errors as errors
28
32
 
29
 
from dialog import error_dialog, info_dialog
30
 
from guifiles import GLADEFILENAME
31
 
 
32
 
 
33
 
class OlivePush:
34
 
    """ Display Push dialog and perform the needed actions. """
35
 
    def __init__(self, branch):
 
33
from dialog import error_dialog, info_dialog, question_dialog
 
34
 
 
35
from history import UrlHistory
 
36
 
 
37
class PushDialog(gtk.Dialog):
 
38
    """ New implementation of the Push dialog. """
 
39
    def __init__(self, repository, revid, branch=None, parent=None):
36
40
        """ Initialize the Push dialog. """
37
 
        self.glade = gtk.glade.XML(GLADEFILENAME, 'window_push')
 
41
        gtk.Dialog.__init__(self, title="Push - Olive",
 
42
                                  parent=parent,
 
43
                                  flags=0,
 
44
                                  buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
38
45
        
39
 
        self.window = self.glade.get_widget('window_push')
40
 
 
 
46
        # Get arguments
 
47
        self.repository = repository
 
48
        self.revid = revid
41
49
        self.branch = branch
42
50
        
43
 
        # Dictionary for signal_autoconnect
44
 
        dic = { "on_button_push_push_clicked": self.push,
45
 
                "on_button_push_cancel_clicked": self.close,
46
 
                "on_button_push_test_clicked": self.test,
47
 
                "on_radiobutton_push_stored_toggled": self.stored_toggled,
48
 
                "on_radiobutton_push_specific_toggled": self.specific_toggled, }
49
 
        
50
 
        # Connect the signals to the handlers
51
 
        self.glade.signal_autoconnect(dic)
52
 
        
53
 
        # Get some useful widgets
54
 
        self.radio_stored = self.glade.get_widget('radiobutton_push_stored')
55
 
        self.radio_specific = self.glade.get_widget('radiobutton_push_specific')
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')
61
 
        self.label_test = self.glade.get_widget('label_push_test')
62
 
        self.image_test = self.glade.get_widget('image_push_test')
63
 
        
64
 
        # Set initial state
65
 
        self.entry_location.set_sensitive(0)
66
 
        self.check_remember.set_sensitive(0)
67
 
        self.check_create.set_sensitive(0)
68
 
        
69
 
        self.entry_stored.set_text(branch.get_push_location() or '')
70
 
    
71
 
    def display(self):
72
 
        """ Display the Push dialog. """
73
 
        self.window.show()
74
 
        self.width, self.height = self.window.get_size()
75
 
    
76
 
    def stored_toggled(self, widget):
77
 
        if widget.get_active():
78
 
            self.entry_stored.set_sensitive(1)
79
 
            self.entry_location.set_sensitive(0)
80
 
            self.check_remember.set_sensitive(0)
81
 
            self.check_create.set_sensitive(0)
82
 
        else:
83
 
            self.entry_stored.set_sensitive(0)
84
 
            self.entry_location.set_sensitive(1)
85
 
            self.check_remember.set_sensitive(1)
86
 
            self.check_create.set_sensitive(1)
87
 
    
88
 
    def specific_toggled(self, widget):
89
 
        if widget.get_active():
90
 
            self.entry_stored.set_sensitive(0)
91
 
            self.entry_location.set_sensitive(1)
92
 
            self.check_remember.set_sensitive(1)
93
 
            self.check_create.set_sensitive(1)
94
 
        else:
95
 
            self.entry_stored.set_sensitive(1)
96
 
            self.entry_location.set_sensitive(0)
97
 
            self.check_remember.set_sensitive(0)
98
 
            self.check_create.set_sensitive(0)
99
 
    
100
 
    def push(self, widget):
 
51
        # Create the widgets
 
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()
 
56
        
 
57
        # Set callbacks
 
58
        self._button_push.connect('clicked', self._on_push_clicked)
 
59
        
 
60
        # Set properties
 
61
        self._label_location.set_alignment(0, 0.5)
 
62
        self._hbox_location.set_spacing(3)
 
63
        self.vbox.set_spacing(3)
 
64
        
 
65
        # Pack widgets
 
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)
 
70
        
 
71
        # Show the dialog
 
72
        self.vbox.show_all()
 
73
        
 
74
        # Build location history
 
75
        self._history = UrlHistory(self.branch.get_config(), 'push_history')
 
76
        self._build_history()
 
77
        
 
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)
 
85
        
 
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)
 
90
    
 
91
    @show_bzr_error
 
92
    def _on_push_clicked(self, widget):
 
93
        """ Push button clicked handler. """
 
94
        location = self._combo.get_child().get_text()
101
95
        revs = 0
102
 
        if self.radio_stored.get_active():
103
 
            try:
104
 
                revs = do_push(self.branch,
105
 
                               overwrite=self.check_overwrite.get_active())
106
 
            except errors.DivergedBranches:
107
 
                response = question_dialog(_('Branches have been diverged'),
108
 
                             _('You cannot push if branches have diverged. \nOverwrite?'))
109
 
                if response == gtk.RESPONSE_OK:
110
 
                    revs = do_push(self.branch, overwrite=True)
111
 
                return
112
 
        elif self.radio_specific.get_active():
113
 
            location = self.entry_location.get_text()
114
 
            if location == '':
115
 
                error_dialog(_('No location specified'),
116
 
                             _('Please specify a location or use the default.'))
117
 
                return
118
 
            
119
 
            try:
120
 
                revs = do_push(self.branch, location,
121
 
                               self.check_remember.get_active(),
122
 
                               False,
123
 
                               self.check_create.get_active())
124
 
            except errors.DivergedBranches:
125
 
                response = question_dialog(_('Branches have been diverged'),
126
 
                             _('You cannot push if branches have diverged. \nOverwrite?'))
127
 
                if response == gtk.RESPONSE_OK:
128
 
                    revs = do_push(self.branch, location,
129
 
                        self.check_remember.get_active(),
130
 
                            True,
131
 
                            self.check_create.get_active())
132
 
                else:
133
 
                    return
 
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.REPONSE_OK:
 
100
                self.branch.set_push_location(location)
 
101
 
 
102
        try:
 
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_OK:
 
108
                revs = do_push(self.branch, location=location, overwrite=True)
 
109
            return
134
110
        
135
 
        self.close()
 
111
        self._history.add_entry(location)
136
112
        info_dialog(_('Push successful'),
137
 
                    _('%d revision(s) pushed.') % revs)
138
 
    
139
 
    def test(self, widget):
140
 
        """ Test if write access possible. """
141
 
        import re
142
 
        _urlRE = re.compile(r'^(?P<proto>[^:/\\]+)://(?P<path>.*)$')
143
 
        
144
 
        if self.radio_stored.get_active():
145
 
            url = self.entry_stored.get_text()
146
 
        elif self.radio_specific.get_active():
147
 
            url = self.entry_location.get_text()
148
 
        
149
 
        m = _urlRE.match(url)
150
 
        if m:
151
 
            proto = m.groupdict()['proto']
152
 
            if (proto == 'sftp') or (proto == 'file') or (proto == 'ftp'):
153
 
                # have write acces (most probably)
154
 
                self.image_test.set_from_stock(gtk.STOCK_YES, 4)
155
 
                self.label_test.set_markup(_('<b>Write access is probably available</b>'))
156
 
            else:
157
 
                # no write access
158
 
                self.image_test.set_from_stock(gtk.STOCK_NO, 4)
159
 
                self.label_test.set_markup(_('<b>No write access</b>'))
160
 
        else:
161
 
            # couldn't determine
162
 
            self.image_test.set_from_stock(gtk.STOCK_DIALOG_QUESTION, 4)
163
 
            self.label_test.set_markup(_('<b>Could not determine</b>'))
164
 
    
165
 
    def close(self, widget=None):
166
 
        self.window.destroy()
 
113
                    _("%d revision(s) pushed.") % revs)
 
114
        
 
115
        self.response(gtk.RESPONSE_OK)
167
116
 
168
 
def do_push(branch, location=None, remember=False, overwrite=False,
169
 
         create_prefix=False):
 
117
def do_push(br_from, location, overwrite):
170
118
    """ Update a mirror of a branch.
171
119
    
172
 
    :param branch: the source branch
 
120
    :param br_from: the source branch
173
121
    
174
122
    :param location: the location of the branch that you'd like to update
175
123
    
176
 
    :param remember: if set, the location will be stored
177
 
    
178
124
    :param overwrite: overwrite target location if it diverged
179
125
    
180
 
    :param create_prefix: create the path leading up to the branch if it doesn't exist
181
 
    
182
126
    :return: number of revisions pushed
183
127
    """
184
 
    from bzrlib.branch import Branch
185
128
    from bzrlib.bzrdir import BzrDir
186
129
    from bzrlib.transport import get_transport
187
130
        
188
 
    br_from = branch
189
 
    
190
 
    stored_loc = br_from.get_push_location()
191
 
    if location is None:
192
 
        if stored_loc is None:
193
 
            error_dialog(_('Push location is unknown'),
194
 
                         _('Please specify a location manually.'))
195
 
            return
196
 
        else:
197
 
            location = stored_loc
198
 
 
199
131
    transport = get_transport(location)
200
132
    location_url = transport.base
201
133
 
202
 
    if br_from.get_push_location() is None or remember:
203
 
        br_from.set_push_location(location_url)
204
 
 
205
134
    old_rh = []
206
135
 
207
136
    try:
210
139
    except errors.NotBranchError:
211
140
        # create a branch.
212
141
        transport = transport.clone('..')
213
 
        if not create_prefix:
214
 
            try:
215
 
                relurl = transport.relpath(location_url)
216
 
                transport.mkdir(relurl)
217
 
            except errors.NoSuchFile:
218
 
                error_dialog(_('Non existing parent directory'),
219
 
                             _("The parent directory (%s)\ndoesn't exist.") % location)
 
142
        try:
 
143
            relurl = transport.relpath(location_url)
 
144
            transport.mkdir(relurl)
 
145
        except errors.NoSuchFile:
 
146
            response = question_dialog(_('Non existing parent directory'),
 
147
                         _("The parent directory (%s)\ndoesn't exist. Create?") % location)
 
148
            if response == gtk.RESPONSE_OK:
 
149
                _create_prefix(transport)
 
150
            else:
220
151
                return
221
 
        else:
222
 
            current = transport.base
223
 
            needed = [(transport, transport.relpath(location_url))]
224
 
            while needed:
225
 
                try:
226
 
                    transport, relpath = needed[-1]
227
 
                    transport.mkdir(relpath)
228
 
                    needed.pop()
229
 
                except errors.NoSuchFile:
230
 
                    new_transport = transport.clone('..')
231
 
                    needed.append((new_transport,
232
 
                                   new_transport.relpath(transport.base)))
233
 
                    if new_transport.base == transport.base:
234
 
                        error_dialog(_('Path prefix not created'),
235
 
                                     _("The path leading up to the specified location couldn't\nbe created."))
236
 
                        return
237
152
        dir_to = br_from.bzrdir.clone(location_url,
238
153
            revision_id=br_from.last_revision())
239
154
        br_to = dir_to.open_branch()
244
159
            tree_to = dir_to.open_workingtree()
245
160
        except errors.NotLocalUrl:
246
161
            # FIXME - what to do here? how should we warn the user?
247
 
            #warning('This transport does not update the working '
248
 
            #        'tree of: %s' % (br_to.base,))
249
162
            count = br_to.pull(br_from, overwrite)
250
163
        except errors.NoWorkingTree:
251
164
            count = br_to.pull(br_from, overwrite)